Skip to content

Commit e22fa4f

Browse files
authored
[ty] Fix method calls on subclasses of Any (#23248)
## Summary Another small win in terms of typing conformance. This should fix the last remaining test in [`specialtypes_any.py`](https://shark.fish/typing-conformance-report/specialtypes_any.html) ## Ecosystem The new diagnostics look like true positives (in our current strict interpretation of LSP checks) ## Test Plan New Markdown test
1 parent fa56c15 commit e22fa4f

3 files changed

Lines changed: 20 additions & 22 deletions

File tree

crates/ty_python_semantic/resources/mdtest/call/methods.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,21 @@ def _(a: object, b: SupportsStr, c: Falsy, d: AlwaysFalsy, e: None, f: Foo | Non
233233
f.__str__()
234234
```
235235

236+
## Method calls on subclasses of `Any`
237+
238+
```py
239+
from typing_extensions import assert_type, Any
240+
241+
class SubclassOfAny(Any):
242+
def method(self) -> int:
243+
return 1
244+
245+
a = SubclassOfAny()
246+
assert_type(a.method(), int)
247+
248+
assert_type(a.non_existing_method(), Any)
249+
```
250+
236251
## Error cases: Calling `__get__` for methods
237252

238253
The `__get__` method on `types.FunctionType` has the following overloaded signature in typeshed:

crates/ty_python_semantic/src/place.rs

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::semantic_index::{DeclarationWithConstraint, global_scope, use_def_map
1515
use crate::types::{
1616
ApplyTypeMappingVisitor, DynamicType, KnownClass, MaterializationKind, MemberLookupPolicy,
1717
Truthiness, Type, TypeAndQualifiers, TypeQualifiers, UnionBuilder, UnionType, binding_type,
18-
declaration_type, todo_type,
18+
declaration_type,
1919
};
2020
use crate::{Db, FxOrderSet, Program};
2121

@@ -174,13 +174,6 @@ impl<'db> Place<'db> {
174174
Place::Defined(DefinedPlace::new(ty.into()).with_origin(TypeOrigin::Declared))
175175
}
176176

177-
/// Constructor that creates a [`Place`] with a [`crate::types::TodoType`] type
178-
/// and definedness [`Definedness::AlwaysDefined`].
179-
#[allow(unused_variables)] // Only unused in release builds
180-
pub(crate) fn todo(message: &'static str) -> Self {
181-
Place::Defined(DefinedPlace::new(todo_type!(message)))
182-
}
183-
184177
pub(crate) fn is_undefined(&self) -> bool {
185178
matches!(self, Place::Undefined)
186179
}
@@ -675,17 +668,6 @@ pub(crate) struct PlaceAndQualifiers<'db> {
675668
}
676669

677670
impl<'db> PlaceAndQualifiers<'db> {
678-
/// Constructor that creates a [`PlaceAndQualifiers`] instance with a [`TodoType`] type
679-
/// and no qualifiers.
680-
///
681-
/// [`TodoType`]: crate::types::TodoType
682-
pub(crate) fn todo(message: &'static str) -> Self {
683-
Self {
684-
place: Place::todo(message),
685-
qualifiers: TypeQualifiers::empty(),
686-
}
687-
}
688-
689671
pub(crate) fn unbound() -> Self {
690672
Self::default()
691673
}

crates/ty_python_semantic/src/types/class.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6111,9 +6111,10 @@ impl<'db, I: Iterator<Item = ClassBase<'db>>> MroLookup<'db, I> {
61116111
// Skip over these very special class bases that aren't really classes.
61126112
}
61136113
ClassBase::Dynamic(_) => {
6114-
return InstanceMemberResult::Done(PlaceAndQualifiers::todo(
6115-
"instance attribute on class with dynamic base",
6116-
));
6114+
// We already return the dynamic type for class member lookup, so we can
6115+
// just return unbound here (to avoid having to build a union of the
6116+
// dynamic type with itself).
6117+
return InstanceMemberResult::Done(PlaceAndQualifiers::unbound());
61176118
}
61186119
ClassBase::Class(class) => {
61196120
if let member @ PlaceAndQualifiers {

0 commit comments

Comments
 (0)