Skip to content

Commit cee6385

Browse files
committed
Address failing tests
1 parent b164ed6 commit cee6385

File tree

6 files changed

+41
-20
lines changed

6 files changed

+41
-20
lines changed

crates/ty_python_semantic/resources/mdtest/narrow/type_guards.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@ def _(
1414
b: TypeIs[str | int],
1515
c: TypeGuard[Intersection[complex, Not[int], Not[float]]],
1616
d: TypeIs[tuple[TypeOf[bytes]]],
17+
e: TypeGuard, # error: [invalid-type-form]
18+
f: TypeIs, # error: [invalid-type-form]
1719
):
1820
# TODO: Should be `TypeGuard[str]`
1921
reveal_type(a) # revealed: @Todo(`TypeGuard[]` special form)
2022
reveal_type(b) # revealed: TypeIs[str | int]
2123
# TODO: Should be `TypeGuard[complex & ~int & ~float]`
2224
reveal_type(c) # revealed: @Todo(`TypeGuard[]` special form)
2325
reveal_type(d) # revealed: TypeIs[tuple[<class 'bytes'>]]
26+
reveal_type(e) # revealed: Unknown
27+
reveal_type(f) # revealed: Unknown
2428

2529
# TODO: error: [invalid-return-type] "Function can implicitly return `None`, which is not assignable to return type `TypeGuard[str]`"
2630
def _(a) -> TypeGuard[str]: ...
@@ -137,12 +141,12 @@ def g(a: Literal["foo", "bar"]) -> TypeIs[Literal["foo"]]:
137141

138142
## Invalid calls
139143

140-
```pyi
144+
```py
141145
from typing import Any
142146
from typing_extensions import TypeGuard, TypeIs
143147

144-
def f(a: object) -> TypeGuard[str]: ...
145-
def g(a: object) -> TypeIs[int]: ...
148+
def f(a: object) -> TypeGuard[str]: return True
149+
def g(a: object) -> TypeIs[int]: return True
146150
def _(d: Any):
147151
if f(): # error: [missing-argument]
148152
...
@@ -158,7 +162,7 @@ def _(d: Any):
158162
...
159163

160164
def _(a: tuple[str, int] | tuple[int, str]):
161-
if g(a[0]): # error: [invalid-type-guard-call]
165+
if g(a[0]):
162166
# TODO: Should be `tuple[str, int]`
163167
reveal_type(a) # revealed: tuple[str, int] | tuple[int, str]
164168
```
@@ -219,10 +223,10 @@ def _(x: str | int, flag: bool) -> None:
219223

220224
```py
221225
from typing import Any
222-
from typing_extensions import TypeGuard
226+
from typing_extensions import TypeGuard, TypeIs
223227

224228
def guard_int(a: object) -> TypeGuard[int]: return True
225-
def is_int(a: object) -> TypeGuard[int]: return True
229+
def is_int(a: object) -> TypeIs[int]: return True
226230
def does_not_narrow_in_negative_case(a: str | int):
227231
if not guard_int(a):
228232
# TODO: Should be `str`

crates/ty_python_semantic/resources/mdtest/type_properties/is_disjoint_from.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,17 @@ static_assert(is_disjoint_from(TypeOf[C.prop], D))
402402
static_assert(is_disjoint_from(D, TypeOf[C.prop]))
403403
```
404404

405+
### `TypeGuard` and `TypeIs`
406+
407+
```py
408+
from ty_extensions import static_assert, is_disjoint_from
409+
from typing_extensions import TypeIs
410+
411+
# TODO: TypeGuard
412+
# static_assert(not is_disjoint_from(bool, TypeGuard[str]))
413+
static_assert(not is_disjoint_from(bool, TypeIs[str]))
414+
```
415+
405416
## Callables
406417

407418
No two callable types are disjoint because there exists a non-empty callable type

crates/ty_python_semantic/resources/mdtest/type_properties/is_subtype_of.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,11 +358,13 @@ from typing_extensions import TypeGuard, TypeIs
358358
`TypeIs` is invariant. `TypeGuard` is covariant.
359359

360360
```py
361-
from ty_extensions import is_subtype_of, static_assert
361+
from ty_extensions import is_equivalent_to, is_subtype_of, static_assert
362362
from typing_extensions import TypeGuard, TypeIs
363363

364364
# TODO: TypeGuard
365+
# static_assert(is_subtype_of(TypeGuard[int], TypeGuard[int]))
365366
# static_assert(is_subtype_of(TypeGuard[bool], TypeGuard[int]))
367+
static_assert(is_subtype_of(TypeIs[int], TypeIs[int]))
366368

367369
static_assert(not is_subtype_of(TypeGuard[int], TypeGuard[bool]))
368370
static_assert(not is_subtype_of(TypeIs[bool], TypeIs[int]))

crates/ty_python_semantic/src/types/infer.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ use super::string_annotation::{
118118
};
119119
use super::subclass_of::SubclassOfInner;
120120
use super::{
121-
BoundSuperError, BoundSuperType, ClassBase, TypeIsType, add_inferred_python_version_hint_to_diagnostic,
121+
BoundSuperError, BoundSuperType, ClassBase, TypeIsType,
122+
add_inferred_python_version_hint_to_diagnostic,
122123
};
123124

124125
/// Infer all types for a [`ScopeId`], including all definitions and expressions in that scope.
@@ -5532,9 +5533,7 @@ impl<'db> TypeInferenceBuilder<'db> {
55325533
Some((symbol, name.to_string()))
55335534
}
55345535
// TODO: Attribute and subscript narrowing
5535-
Some(expr) => {
5536-
None
5537-
}
5536+
Some(_) => None,
55385537
};
55395538

55405539
// TODO: Handle unions/intersections

crates/ty_python_semantic/src/types/narrow.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -742,23 +742,28 @@ impl<'db> NarrowingConstraintsBuilder<'db> {
742742
let return_ty =
743743
inference.expression_type(expr_call.scoped_expression_id(self.db, scope));
744744

745+
if let Some(name) = expr_call.func.as_name_expr() {
746+
dbg!(&name.id);
747+
dbg!(return_ty);
748+
}
749+
745750
// TODO: Handle unions and intersections
746751
let (guarded_ty, symbol) = match return_ty {
747752
// TODO: TypeGuard
748753
Type::TypeIs(type_is) => {
749754
let (_, symbol, _) = type_is.symbol_info(self.db)?;
755+
if let Some(name) = expr_call.func.as_name_expr() {
756+
dbg!(symbol, name);
757+
}
750758
(type_is.ty(self.db), symbol)
751759
}
752760
_ => return None,
753761
};
754762

755-
let mut constraints = NarrowingConstraints::default();
756-
757-
if is_positive {
758-
constraints.insert(symbol, guarded_ty.negate_if(self.db, !is_positive));
759-
}
760-
761-
Some(constraints)
763+
Some(NarrowingConstraints::from_iter([(
764+
symbol,
765+
guarded_ty.negate_if(self.db, !is_positive),
766+
)]))
762767
}
763768
Type::FunctionLiteral(function_type) if expr_call.arguments.keywords.is_empty() => {
764769
let [first_arg, second_arg] = &*expr_call.arguments.args else {

crates/ty_python_semantic/src/types/type_ordering.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use std::cmp::Ordering;
33
use crate::db::Db;
44

55
use super::{
6-
DynamicType, SuperOwnerKind, TodoType, Type, TypeIsType,
7-
class_base::ClassBase, subclass_of::SubclassOfInner,
6+
DynamicType, SuperOwnerKind, TodoType, Type, TypeIsType, class_base::ClassBase,
7+
subclass_of::SubclassOfInner,
88
};
99

1010
/// Return an [`Ordering`] that describes the canonical order in which two types should appear

0 commit comments

Comments
 (0)