[red-knot] fix class vs instance (#11175)

## Summary

Clarify the type of an exact class object vs the type of instances of
that class.

## Test Plan

cargo test
This commit is contained in:
Carl Meyer 2024-04-27 09:09:02 -06:00 committed by GitHub
parent 2490d2d4af
commit 2d6978f236
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 17 additions and 9 deletions

View file

@ -22,10 +22,12 @@ pub enum Type {
Unknown, Unknown,
/// name is not bound to any value /// name is not bound to any value
Unbound, Unbound,
/// a specific function /// a specific function object
Function(FunctionTypeId), Function(FunctionTypeId),
/// the set of Python objects with a given class in their __class__'s method resolution order /// a specific class object
Class(ClassTypeId), Class(ClassTypeId),
/// the set of Python objects with the given class in their __class__'s method resolution order
Instance(ClassTypeId),
Union(UnionTypeId), Union(UnionTypeId),
Intersection(IntersectionTypeId), Intersection(IntersectionTypeId),
// TODO protocols, callable types, overloads, generics, type vars // TODO protocols, callable types, overloads, generics, type vars
@ -349,7 +351,13 @@ impl std::fmt::Display for DisplayType<'_> {
Type::Never => f.write_str("Never"), Type::Never => f.write_str("Never"),
Type::Unknown => f.write_str("Unknown"), Type::Unknown => f.write_str("Unknown"),
Type::Unbound => f.write_str("Unbound"), Type::Unbound => f.write_str("Unbound"),
Type::Class(class_id) => f.write_str(self.store.get_class(*class_id).name()), // TODO functions and classes should display using a fully qualified name
Type::Class(class_id) => {
f.write_str("Literal[")?;
f.write_str(self.store.get_class(*class_id).name())?;
f.write_str("]")
}
Type::Instance(class_id) => f.write_str(self.store.get_class(*class_id).name()),
Type::Function(func_id) => f.write_str(self.store.get_function(*func_id).name()), Type::Function(func_id) => f.write_str(self.store.get_function(*func_id).name()),
Type::Union(union_id) => self Type::Union(union_id) => self
.store .store
@ -459,8 +467,8 @@ mod tests {
let file_id = files.intern(Path::new("/foo")); let file_id = files.intern(Path::new("/foo"));
let id = store.add_class(file_id, "C"); let id = store.add_class(file_id, "C");
assert_eq!(store.get_class(id).name(), "C"); assert_eq!(store.get_class(id).name(), "C");
let class = Type::Class(id); let inst = Type::Instance(id);
assert_eq!(format!("{}", class.display(&store)), "C"); assert_eq!(format!("{}", inst.display(&store)), "C");
} }
#[test] #[test]
@ -481,7 +489,7 @@ mod tests {
let file_id = files.intern(Path::new("/foo")); let file_id = files.intern(Path::new("/foo"));
let c1 = store.add_class(file_id, "C1"); let c1 = store.add_class(file_id, "C1");
let c2 = store.add_class(file_id, "C2"); let c2 = store.add_class(file_id, "C2");
let elems = vec![Type::Class(c1), Type::Class(c2)]; let elems = vec![Type::Instance(c1), Type::Instance(c2)];
let id = store.add_union(file_id, &elems); let id = store.add_union(file_id, &elems);
assert_eq!( assert_eq!(
store.get_union(id).elements, store.get_union(id).elements,
@ -499,8 +507,8 @@ mod tests {
let c1 = store.add_class(file_id, "C1"); let c1 = store.add_class(file_id, "C1");
let c2 = store.add_class(file_id, "C2"); let c2 = store.add_class(file_id, "C2");
let c3 = store.add_class(file_id, "C3"); let c3 = store.add_class(file_id, "C3");
let pos = vec![Type::Class(c1), Type::Class(c2)]; let pos = vec![Type::Instance(c1), Type::Instance(c2)];
let neg = vec![Type::Class(c3)]; let neg = vec![Type::Instance(c3)];
let id = store.add_intersection(file_id, &pos, &neg); let id = store.add_intersection(file_id, &pos, &neg);
assert_eq!( assert_eq!(
store.get_intersection(id).positive, store.get_intersection(id).positive,

View file

@ -135,7 +135,7 @@ mod tests {
let jar = HasJar::<SemanticJar>::jar(&db); let jar = HasJar::<SemanticJar>::jar(&db);
assert!(matches!(ty, Type::Class(_))); assert!(matches!(ty, Type::Class(_)));
assert_eq!(format!("{}", ty.display(&jar.type_store)), "C"); assert_eq!(format!("{}", ty.display(&jar.type_store)), "Literal[C]");
Ok(()) Ok(())
} }
} }