[ty] fix infinite recursion bug in is_disjoint_from (#18043)

## Summary

I found this bug while working on #18041. The following code leads to
infinite recursion.

```python
from ty_extensions import is_disjoint_from, static_assert, TypeOf

class C:
    @property
    def prop(self) -> int:
        return 1

static_assert(not is_disjoint_from(int, TypeOf[C.prop]))
```

The cause is a trivial missing binding in `is_disjoint_from`. This PR
fixes the bug and adds a test case (this is a simple fix and may not
require a new test case?).

## Test Plan

A new test case is added to
`mdtest/type_properties/is_disjoint_from.md`.
This commit is contained in:
Shunsuke Shibayama 2025-05-12 22:44:00 +09:00 committed by GitHub
parent 797eb70904
commit 6f8f7506b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 28 additions and 3 deletions

View file

@ -375,6 +375,29 @@ class UsesMeta2(metaclass=Meta2): ...
static_assert(is_disjoint_from(type[UsesMeta1], type[UsesMeta2])) static_assert(is_disjoint_from(type[UsesMeta1], type[UsesMeta2]))
``` ```
### `property`
```py
from ty_extensions import is_disjoint_from, static_assert, TypeOf
from typing import final
class C:
@property
def prop(self) -> int:
return 1
reveal_type(C.prop) # revealed: property
@final
class D:
pass
static_assert(not is_disjoint_from(int, TypeOf[C.prop]))
static_assert(not is_disjoint_from(TypeOf[C.prop], int))
static_assert(is_disjoint_from(TypeOf[C.prop], D))
static_assert(is_disjoint_from(D, TypeOf[C.prop]))
```
## Callables ## Callables
No two callable types are disjoint because there exists a non-empty callable type No two callable types are disjoint because there exists a non-empty callable type

View file

@ -2101,9 +2101,11 @@ impl<'db> Type<'db> {
instance.is_disjoint_from(db, KnownClass::Tuple.to_instance(db)) instance.is_disjoint_from(db, KnownClass::Tuple.to_instance(db))
} }
(Type::PropertyInstance(_), _) | (_, Type::PropertyInstance(_)) => KnownClass::Property (Type::PropertyInstance(_), other) | (other, Type::PropertyInstance(_)) => {
.to_instance(db) KnownClass::Property
.is_disjoint_from(db, other), .to_instance(db)
.is_disjoint_from(db, other)
}
(Type::BoundSuper(_), Type::BoundSuper(_)) => !self.is_equivalent_to(db, other), (Type::BoundSuper(_), Type::BoundSuper(_)) => !self.is_equivalent_to(db, other),
(Type::BoundSuper(_), other) | (other, Type::BoundSuper(_)) => KnownClass::Super (Type::BoundSuper(_), other) | (other, Type::BoundSuper(_)) => KnownClass::Super