From e2a38e4c0090cee5c20bde86a8ca9b30bffb2cfa Mon Sep 17 00:00:00 2001 From: Carl Meyer Date: Mon, 14 Apr 2025 09:42:44 -0700 Subject: [PATCH] [red-knot] optimize is_subtype_of for literals (#17394) ## Summary Allows us to establish that two literals do not have a subtype relationship with each other, without having to fallback to a typeshed Instance type, which is comparatively slow. Improves the performance of the many-string-literals union benchmark by 5x. ## Test Plan `cargo test -p red_knot_python_semantic` and `cargo bench --bench red_knot`. --- crates/red_knot_python_semantic/src/types.rs | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/crates/red_knot_python_semantic/src/types.rs b/crates/red_knot_python_semantic/src/types.rs index 00ac8377be..f72ac96941 100644 --- a/crates/red_knot_python_semantic/src/types.rs +++ b/crates/red_knot_python_semantic/src/types.rs @@ -886,6 +886,27 @@ impl<'db> Type<'db> { target.is_equivalent_to(db, Type::object(db)) } + // No literal type is a subtype of any other literal type, unless they are the same + // type (which is handled above). This case is not necessary from a correctness + // perspective (the fallback cases below will handle it correctly), but it is important + // for performance of simplifying large unions of literal types. + ( + Type::StringLiteral(_) + | Type::IntLiteral(_) + | Type::BytesLiteral(_) + | Type::ClassLiteral(_) + | Type::FunctionLiteral(_) + | Type::ModuleLiteral(_) + | Type::SliceLiteral(_), + Type::StringLiteral(_) + | Type::IntLiteral(_) + | Type::BytesLiteral(_) + | Type::ClassLiteral(_) + | Type::FunctionLiteral(_) + | Type::ModuleLiteral(_) + | Type::SliceLiteral(_), + ) => false, + // All `StringLiteral` types are a subtype of `LiteralString`. (Type::StringLiteral(_), Type::LiteralString) => true,