diff --git a/crates/red_knot_python_semantic/resources/mdtest/metaclass.md b/crates/red_knot_python_semantic/resources/mdtest/metaclass.md index a8056d1903..531f668265 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/metaclass.md +++ b/crates/red_knot_python_semantic/resources/mdtest/metaclass.md @@ -68,7 +68,7 @@ class B(metaclass=M2): ... # error: [conflicting-metaclass] "The metaclass of a derived class (`C`) must be a subclass of the metaclasses of all its bases, but `M1` (metaclass of base class `A`) and `M2` (metaclass of base class `B`) have no subclass relationship" class C(A, B): ... -reveal_type(C.__class__) # revealed: Unknown +reveal_type(C.__class__) # revealed: type[Unknown] ``` ## Conflict (2) @@ -85,7 +85,7 @@ class A(metaclass=M1): ... # error: [conflicting-metaclass] "The metaclass of a derived class (`B`) must be a subclass of the metaclasses of all its bases, but `M2` (metaclass of `B`) and `M1` (metaclass of base class `A`) have no subclass relationship" class B(A, metaclass=M2): ... -reveal_type(B.__class__) # revealed: Unknown +reveal_type(B.__class__) # revealed: type[Unknown] ``` ## Common metaclass @@ -129,7 +129,7 @@ class C(metaclass=M12): ... # error: [conflicting-metaclass] "The metaclass of a derived class (`D`) must be a subclass of the metaclasses of all its bases, but `M1` (metaclass of base class `A`) and `M2` (metaclass of base class `B`) have no subclass relationship" class D(A, B, C): ... -reveal_type(D.__class__) # revealed: Unknown +reveal_type(D.__class__) # revealed: type[Unknown] ``` ## Unknown @@ -183,7 +183,7 @@ class A(B): ... # error: [cyclic-class-definition] class B(C): ... # error: [cyclic-class-definition] class C(A): ... # error: [cyclic-class-definition] -reveal_type(A.__class__) # revealed: Unknown +reveal_type(A.__class__) # revealed: type[Unknown] ``` ## PEP 695 generic diff --git a/crates/red_knot_python_semantic/src/types.rs b/crates/red_knot_python_semantic/src/types.rs index 4d9ea40ab3..59842f08db 100644 --- a/crates/red_knot_python_semantic/src/types.rs +++ b/crates/red_knot_python_semantic/src/types.rs @@ -2925,10 +2925,10 @@ impl<'db> Class<'db> { Some(metaclass_ty) } - /// Return the metaclass of this class, or `Unknown` if the metaclass cannot be inferred. + /// Return the metaclass of this class, or `type[Unknown]` if the metaclass cannot be inferred. pub(crate) fn metaclass(self, db: &'db dyn Db) -> Type<'db> { - // TODO: `type[Unknown]` would be a more precise fallback - self.try_metaclass(db).unwrap_or(Type::Unknown) + self.try_metaclass(db) + .unwrap_or_else(|_| Type::subclass_of_base(ClassBase::Unknown)) } /// Return the metaclass of this class, or an error if the metaclass cannot be inferred. @@ -2941,9 +2941,7 @@ impl<'db> Class<'db> { // We emit diagnostics for cyclic class definitions elsewhere. // Avoid attempting to infer the metaclass if the class is cyclically defined: // it would be easy to enter an infinite loop. - // - // TODO: `type[Unknown]` might be better here? - return Ok(Type::Unknown); + return Ok(Type::subclass_of_base(ClassBase::Unknown)); } let explicit_metaclass = self.explicit_metaclass(db);