From 27b715215972f0526890df3e2d82549c239d75f3 Mon Sep 17 00:00:00 2001 From: Eric Mark Martin Date: Mon, 17 Nov 2025 20:45:01 -0500 Subject: [PATCH] some cleanup --- .../mdtest/annotations/unsupported_special_forms.md | 3 --- .../resources/mdtest/narrow/type_guards.md | 7 ++----- crates/ty_python_semantic/src/types.rs | 3 ++- crates/ty_python_semantic/src/types/narrow.rs | 9 ++++----- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/crates/ty_python_semantic/resources/mdtest/annotations/unsupported_special_forms.md b/crates/ty_python_semantic/resources/mdtest/annotations/unsupported_special_forms.md index 6c0947c5e0..50df54b556 100644 --- a/crates/ty_python_semantic/resources/mdtest/annotations/unsupported_special_forms.md +++ b/crates/ty_python_semantic/resources/mdtest/annotations/unsupported_special_forms.md @@ -16,9 +16,6 @@ def f(*args: Unpack[Ts]) -> tuple[Unpack[Ts]]: reveal_type(args) # revealed: tuple[@Todo(`Unpack[]` special form), ...] return args -def g() -> TypeGuard[int]: - return True - def i(callback: Callable[Concatenate[int, P], R_co], *args: P.args, **kwargs: P.kwargs) -> R_co: reveal_type(args) # revealed: P@i.args reveal_type(kwargs) # revealed: P@i.kwargs diff --git a/crates/ty_python_semantic/resources/mdtest/narrow/type_guards.md b/crates/ty_python_semantic/resources/mdtest/narrow/type_guards.md index c2a5f8feb6..fdd5a5aee6 100644 --- a/crates/ty_python_semantic/resources/mdtest/narrow/type_guards.md +++ b/crates/ty_python_semantic/resources/mdtest/narrow/type_guards.md @@ -12,17 +12,14 @@ from typing_extensions import TypeGuard, TypeIs def _( a: TypeGuard[str], b: TypeIs[str | int], - c: TypeGuard[Intersection[complex, Not[int], Not[float]]], + c: TypeGuard[bool], d: TypeIs[tuple[TypeOf[bytes]]], e: TypeGuard, # error: [invalid-type-form] f: TypeIs, # error: [invalid-type-form] ): reveal_type(a) # revealed: TypeGuard[str] reveal_type(b) # revealed: TypeIs[str | int] - # not `TypeGuard[complex & ~int & ~float]`: `complex` in argument position - # means `complex & int & float` semantically so `Intersection[complex, - # Not[int], Not[float]]` means `complex` semantically - reveal_type(c) # revealed: TypeGuard[complex] + reveal_type(c) # revealed: TypeGuard[bool] reveal_type(d) # revealed: TypeIs[tuple[]] reveal_type(e) # revealed: Unknown reveal_type(f) # revealed: Unknown diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index 1d6a28b3d1..94f33c07f7 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -14750,7 +14750,8 @@ impl<'db> TypeGuardType<'db> { } impl<'db> VarianceInferable<'db> for TypeGuardType<'db> { - // TODO: comment + // `TypeGuard` is covariant in its type parameter. See the `TypeGuard` + // section of mdtest/generics/pep695/variance.md for details. fn variance_of(self, db: &'db dyn Db, typevar: BoundTypeVarInstance<'db>) -> TypeVarVariance { self.return_type(db).variance_of(db, typevar) } diff --git a/crates/ty_python_semantic/src/types/narrow.rs b/crates/ty_python_semantic/src/types/narrow.rs index b7cdf10e02..f5cf1b4d38 100644 --- a/crates/ty_python_semantic/src/types/narrow.rs +++ b/crates/ty_python_semantic/src/types/narrow.rs @@ -288,10 +288,9 @@ impl ClassInfoConstraintFunction { /// in the second clobbers the first. #[derive(Hash, PartialEq, Debug, Eq, Clone, Copy)] struct Conjunction<'db> { - /// The intersected constraints (represented as an intersection type) + /// The intersected constraints (represented as a type to intersect the guard with) constraint: Type<'db>, - /// If any constraint in this conjunction is a `TypeGuard`, this is Some and - /// contains the union of all `TypeGuard` types in this conjunction + /// If any constraint in this conjunction is a `TypeGuard[T]`, this is `Some(T)` typeguard: Option>, } @@ -343,10 +342,10 @@ impl<'db> Conjunction<'db> { /// /// - `f(x) or g(x)` where f returns `TypeIs[A]` and g returns `TypeGuard[B]` /// => `[Conjunction { constraint: A, typeguard: None }, Conjunction { constraint: object, typeguard: Some(B) }]` -/// => evaluates to `A | B` +/// => evaluates to `(P & A) | B`, where `P` is our previously-known type #[derive(Hash, PartialEq, Debug, Eq, Clone)] struct NarrowingConstraint<'db> { - /// Disjunctions of conjunctions (DNF) + /// Disjunction of conjunctions (DNF) disjuncts: SmallVec<[Conjunction<'db>; 4]>, }