From c87463842a6e19976b6f3401137b6932e4a7bb71 Mon Sep 17 00:00:00 2001 From: David Peter Date: Fri, 10 Jan 2025 16:31:30 +0100 Subject: [PATCH] [red-knot] Move tuple-containing-Never tests to Markdown (#15402) ## Summary See title. Part of #15397 ## Test Plan Ran new Markdown test. --------- Co-authored-by: Alex Waygood --- .../tuples_containing_never.md | 33 +++++++++++++++++++ crates/red_knot_python_semantic/src/types.rs | 8 ----- 2 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 crates/red_knot_python_semantic/resources/mdtest/type_properties/tuples_containing_never.md diff --git a/crates/red_knot_python_semantic/resources/mdtest/type_properties/tuples_containing_never.md b/crates/red_knot_python_semantic/resources/mdtest/type_properties/tuples_containing_never.md new file mode 100644 index 0000000000000..027d4943ec839 --- /dev/null +++ b/crates/red_knot_python_semantic/resources/mdtest/type_properties/tuples_containing_never.md @@ -0,0 +1,33 @@ +# Tuples containing `Never` + +A heterogeneous `tuple[…]` type that contains `Never` as a type argument simplifies to `Never`. One +way to think about this is the following: in order to construct a tuple, you need to have an object +of every element type. But since there is no object of type `Never`, you cannot construct the tuple. +Such a tuple type is therefore uninhabited and equivalent to `Never`. + +In the language of algebraic data types, a tuple type is a product type and `Never` acts like the +zero element in multiplication, similar to how a Cartesian product with the empty set is the empty +set. + +```py +from knot_extensions import static_assert, is_equivalent_to +from typing_extensions import Never, NoReturn + +static_assert(is_equivalent_to(Never, tuple[Never])) +static_assert(is_equivalent_to(Never, tuple[Never, int])) +static_assert(is_equivalent_to(Never, tuple[int, Never])) +static_assert(is_equivalent_to(Never, tuple[int, Never, str])) +static_assert(is_equivalent_to(Never, tuple[int, tuple[str, Never]])) +static_assert(is_equivalent_to(Never, tuple[tuple[str, Never], int])) + +# The empty tuple is *not* equivalent to Never! +static_assert(not is_equivalent_to(Never, tuple[()])) + +# NoReturn is just a different spelling of Never, so the same is true for NoReturn +static_assert(is_equivalent_to(NoReturn, tuple[NoReturn])) +static_assert(is_equivalent_to(NoReturn, tuple[NoReturn, int])) +static_assert(is_equivalent_to(NoReturn, tuple[int, NoReturn])) +static_assert(is_equivalent_to(NoReturn, tuple[int, NoReturn, str])) +static_assert(is_equivalent_to(NoReturn, tuple[int, tuple[str, NoReturn]])) +static_assert(is_equivalent_to(NoReturn, tuple[tuple[str, NoReturn], int])) +``` diff --git a/crates/red_knot_python_semantic/src/types.rs b/crates/red_knot_python_semantic/src/types.rs index 5a2c8e895562d..f13cf71e88b4f 100644 --- a/crates/red_knot_python_semantic/src/types.rs +++ b/crates/red_knot_python_semantic/src/types.rs @@ -4144,14 +4144,6 @@ pub(crate) mod tests { } } - #[test_case(Ty::Tuple(vec![Ty::Never]))] - #[test_case(Ty::Tuple(vec![Ty::BuiltinInstance("str"), Ty::Never, Ty::BuiltinInstance("int")]))] - #[test_case(Ty::Tuple(vec![Ty::Tuple(vec![Ty::Never])]))] - fn tuple_containing_never_simplifies_to_never(ty: Ty) { - let db = setup_db(); - assert_eq!(ty.into_type(&db), Type::Never); - } - #[test_case(Ty::BuiltinInstance("str"), Ty::BuiltinInstance("object"))] #[test_case(Ty::BuiltinInstance("int"), Ty::BuiltinInstance("object"))] #[test_case(Ty::BuiltinInstance("bool"), Ty::BuiltinInstance("object"))]