[red-knot] Add narrowing for issubclass checks#14128
Conversation
|
| Type::Tuple(_) => KnownClass::Tuple.to_class(db), | ||
| // TODO not accurate if there's a custom metaclass... | ||
| Type::ClassLiteral(_) => KnownClass::Type.to_class(db), | ||
| Type::Type(_) => Type::Todo, |
There was a problem hiding this comment.
This is too meta for me. Should this be Type::Type('type')?
There was a problem hiding this comment.
Should this be
Type::Type('type')?
yes, I think so
There was a problem hiding this comment.
For now, sure. But with a TODO comment. Because with Charlie's metaclass PR, it should become something like:
| Type::Type(_) => Type::Todo, | |
| Type::Type(class) => Type::Type(class.class.metaclass(db).expect_literal_class()) |
but with more proper handling of odd cases and less expect
There was a problem hiding this comment.
I tried something, but I'm not sure what kind of "odd cases" would need to be handled. Let me know if something should be changed here (post-merge).
| Type::Tuple(_) => KnownClass::Tuple.to_class(db), | ||
| // TODO not accurate if there's a custom metaclass... | ||
| Type::ClassLiteral(_) => KnownClass::Type.to_class(db), | ||
| Type::Type(_) => Type::Todo, |
There was a problem hiding this comment.
Should this be
Type::Type('type')?
yes, I think so
carljm
left a comment
There was a problem hiding this comment.
(Haven't finished review yet but need to run to lunch and an errand, will complete review when I get back.)
| Type::Tuple(_) => KnownClass::Tuple.to_class(db), | ||
| // TODO not accurate if there's a custom metaclass... | ||
| Type::ClassLiteral(_) => KnownClass::Type.to_class(db), | ||
| Type::Type(_) => Type::Todo, |
There was a problem hiding this comment.
For now, sure. But with a TODO comment. Because with Charlie's metaclass PR, it should become something like:
| Type::Type(_) => Type::Todo, | |
| Type::Type(class) => Type::Type(class.class.metaclass(db).expect_literal_class()) |
but with more proper handling of odd cases and less expect
7787933 to
0884352
Compare
7cc2599 to
400e101
Compare
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
| ) if self_class | ||
| .metaclass(db) | ||
| .into_class_literal() | ||
| .map(|meta| meta.class.is_subclass_of(db, target_class)) | ||
| .unwrap_or(false) => | ||
| { | ||
| true |
There was a problem hiding this comment.
Looks good! My comment was vague because I hadn't thought through yet the handling of a non-class-literal metaclass here. But I think the only options here are class literal or dynamic type (Any/Unknown/Todo), and since this is is_subtype_of, ignoring dynamic type is correct.
| class | ||
| .try_metaclass(db) | ||
| .ok() | ||
| .and_then(Type::into_class_literal) | ||
| .unwrap_or(KnownClass::Type.to_class(db).expect_class_literal()) | ||
| .to_subclass_of_type(), |
There was a problem hiding this comment.
This looks great, too! Falling back to Type::SubclassOf(builtins.type) in the case of any non-specific metaclass is the right answer here, I think.
Summary
type[C]as a red knotType. Some things might not be supported yet, liketype[Any].issubclasschecks.closes #14117
Test Plan
New Markdown-based tests