Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions crates/ty_python_semantic/resources/mdtest/call/methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,21 @@ def _(a: object, b: SupportsStr, c: Falsy, d: AlwaysFalsy, e: None, f: Foo | Non
f.__str__() # error: [missing-argument]
```

## Method calls on subclasses of `Any`

```py
from typing_extensions import assert_type, Any

class SubclassOfAny(Any):
def method(self) -> int:
return 1

a = SubclassOfAny()
assert_type(a.method(), int)

assert_type(a.non_existing_method(), Any)
```

## Error cases: Calling `__get__` for methods

The `__get__` method on `types.FunctionType` has the following overloaded signature in typeshed:
Expand Down
20 changes: 1 addition & 19 deletions crates/ty_python_semantic/src/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::semantic_index::{DeclarationWithConstraint, global_scope, use_def_map
use crate::types::{
ApplyTypeMappingVisitor, DynamicType, KnownClass, MaterializationKind, MemberLookupPolicy,
Truthiness, Type, TypeAndQualifiers, TypeQualifiers, UnionBuilder, UnionType, binding_type,
declaration_type, todo_type,
declaration_type,
};
use crate::{Db, FxOrderSet, Program};

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

/// Constructor that creates a [`Place`] with a [`crate::types::TodoType`] type
/// and definedness [`Definedness::AlwaysDefined`].
#[allow(unused_variables)] // Only unused in release builds
pub(crate) fn todo(message: &'static str) -> Self {
Place::Defined(DefinedPlace::new(todo_type!(message)))
}

pub(crate) fn is_undefined(&self) -> bool {
matches!(self, Place::Undefined)
}
Expand Down Expand Up @@ -675,17 +668,6 @@ pub(crate) struct PlaceAndQualifiers<'db> {
}

impl<'db> PlaceAndQualifiers<'db> {
/// Constructor that creates a [`PlaceAndQualifiers`] instance with a [`TodoType`] type
/// and no qualifiers.
///
/// [`TodoType`]: crate::types::TodoType
pub(crate) fn todo(message: &'static str) -> Self {
Self {
place: Place::todo(message),
qualifiers: TypeQualifiers::empty(),
}
}

pub(crate) fn unbound() -> Self {
Self::default()
}
Expand Down
7 changes: 4 additions & 3 deletions crates/ty_python_semantic/src/types/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6111,9 +6111,10 @@ impl<'db, I: Iterator<Item = ClassBase<'db>>> MroLookup<'db, I> {
// Skip over these very special class bases that aren't really classes.
}
ClassBase::Dynamic(_) => {
return InstanceMemberResult::Done(PlaceAndQualifiers::todo(
"instance attribute on class with dynamic base",
));
// We already return the dynamic type for class member lookup, so we can
// just return unbound here (to avoid having to build a union of the
// dynamic type with itself).
return InstanceMemberResult::Done(PlaceAndQualifiers::unbound());
}
ClassBase::Class(class) => {
if let member @ PlaceAndQualifiers {
Expand Down
Loading