Skip to content

Commit 90a5439

Browse files
authored
[red-knot] Use type[Unknown] rather than Unknown as the fallback metaclass for invalid classes (#14961)
1 parent 4b2b126 commit 90a5439

File tree

2 files changed

+8
-10
lines changed

2 files changed

+8
-10
lines changed

crates/red_knot_python_semantic/resources/mdtest/metaclass.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class B(metaclass=M2): ...
6868
# 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"
6969
class C(A, B): ...
7070

71-
reveal_type(C.__class__) # revealed: Unknown
71+
reveal_type(C.__class__) # revealed: type[Unknown]
7272
```
7373

7474
## Conflict (2)
@@ -85,7 +85,7 @@ class A(metaclass=M1): ...
8585
# 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"
8686
class B(A, metaclass=M2): ...
8787

88-
reveal_type(B.__class__) # revealed: Unknown
88+
reveal_type(B.__class__) # revealed: type[Unknown]
8989
```
9090

9191
## Common metaclass
@@ -129,7 +129,7 @@ class C(metaclass=M12): ...
129129
# 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"
130130
class D(A, B, C): ...
131131

132-
reveal_type(D.__class__) # revealed: Unknown
132+
reveal_type(D.__class__) # revealed: type[Unknown]
133133
```
134134

135135
## Unknown
@@ -183,7 +183,7 @@ class A(B): ... # error: [cyclic-class-definition]
183183
class B(C): ... # error: [cyclic-class-definition]
184184
class C(A): ... # error: [cyclic-class-definition]
185185

186-
reveal_type(A.__class__) # revealed: Unknown
186+
reveal_type(A.__class__) # revealed: type[Unknown]
187187
```
188188

189189
## PEP 695 generic

crates/red_knot_python_semantic/src/types.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2925,10 +2925,10 @@ impl<'db> Class<'db> {
29252925
Some(metaclass_ty)
29262926
}
29272927

2928-
/// Return the metaclass of this class, or `Unknown` if the metaclass cannot be inferred.
2928+
/// Return the metaclass of this class, or `type[Unknown]` if the metaclass cannot be inferred.
29292929
pub(crate) fn metaclass(self, db: &'db dyn Db) -> Type<'db> {
2930-
// TODO: `type[Unknown]` would be a more precise fallback
2931-
self.try_metaclass(db).unwrap_or(Type::Unknown)
2930+
self.try_metaclass(db)
2931+
.unwrap_or_else(|_| Type::subclass_of_base(ClassBase::Unknown))
29322932
}
29332933

29342934
/// Return the metaclass of this class, or an error if the metaclass cannot be inferred.
@@ -2941,9 +2941,7 @@ impl<'db> Class<'db> {
29412941
// We emit diagnostics for cyclic class definitions elsewhere.
29422942
// Avoid attempting to infer the metaclass if the class is cyclically defined:
29432943
// it would be easy to enter an infinite loop.
2944-
//
2945-
// TODO: `type[Unknown]` might be better here?
2946-
return Ok(Type::Unknown);
2944+
return Ok(Type::subclass_of_base(ClassBase::Unknown));
29472945
}
29482946

29492947
let explicit_metaclass = self.explicit_metaclass(db);

0 commit comments

Comments
 (0)