diff --git a/crates/red_knot_python_semantic/src/types/class.rs b/crates/red_knot_python_semantic/src/types/class.rs index 04854b7c2e..a39dd92d9d 100644 --- a/crates/red_knot_python_semantic/src/types/class.rs +++ b/crates/red_knot_python_semantic/src/types/class.rs @@ -995,11 +995,10 @@ impl<'db> KnownClass { | Self::MethodWrapperType | Self::WrapperDescriptorType => KnownModule::Types, Self::NoneType => KnownModule::Typeshed, - Self::SpecialForm - | Self::TypeVar - | Self::TypeAliasType - | Self::StdlibAlias - | Self::SupportsIndex => KnownModule::Typing, + Self::SpecialForm | Self::TypeVar | Self::StdlibAlias | Self::SupportsIndex => { + KnownModule::Typing + } + Self::TypeAliasType => KnownModule::TypingExtensions, Self::NoDefaultType => { let python_version = Program::get(db).python_version(db); @@ -1603,6 +1602,7 @@ mod tests { use super::*; use crate::db::tests::setup_db; use crate::module_resolver::resolve_module; + use salsa::Setter; use strum::IntoEnumIterator; #[test] @@ -1619,4 +1619,44 @@ mod tests { ); } } + + #[test] + fn known_class_doesnt_fallback_to_unknown_unexpectedly_on_latest_version() { + let mut db = setup_db(); + + Program::get(&db) + .set_python_version(&mut db) + .to(PythonVersion::latest()); + + for class in KnownClass::iter() { + assert_ne!( + class.to_instance(&db), + Type::unknown(), + "Unexpectedly fell back to `Unknown` for `{class:?}`" + ); + } + } + + #[test] + fn known_class_doesnt_fallback_to_unknown_unexpectedly_on_low_python_version() { + let mut db = setup_db(); + + for class in KnownClass::iter() { + let version_added = match class { + KnownClass::BaseExceptionGroup => PythonVersion::PY311, + KnownClass::GenericAlias => PythonVersion::PY39, + _ => PythonVersion::PY37, + }; + + Program::get(&db) + .set_python_version(&mut db) + .to(version_added); + + assert_ne!( + class.to_instance(&db), + Type::unknown(), + "Unexpectedly fell back to `Unknown` for `{class:?}` on Python {version_added}" + ); + } + } }