Skip to content

[red-knot] Add narrowing for issubclass checks#14128

Merged
sharkdp merged 23 commits intomainfrom
david/issubclass-narrowing
Nov 7, 2024
Merged

[red-knot] Add narrowing for issubclass checks#14128
sharkdp merged 23 commits intomainfrom
david/issubclass-narrowing

Conversation

@sharkdp
Copy link
Contributor

@sharkdp sharkdp commented Nov 6, 2024

Summary

  • Adds basic support for type[C] as a red knot Type. Some things might not be supported yet, like type[Any].
  • Adds type narrowing for issubclass checks.

closes #14117

Test Plan

New Markdown-based tests

@sharkdp sharkdp added the ty Multi-file analysis & type inference label Nov 6, 2024
@github-actions
Copy link
Contributor

github-actions bot commented Nov 6, 2024

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

@sharkdp sharkdp marked this pull request as ready for review November 6, 2024 14:57
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,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is too meta for me. Should this be Type::Type('type')?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be Type::Type('type')?

yes, I think so

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, sure. But with a TODO comment. Because with Charlie's metaclass PR, it should become something like:

Suggested change
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

Copy link
Contributor Author

@sharkdp sharkdp Nov 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copy link
Member

@AlexWaygood AlexWaygood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very cool!

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,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be Type::Type('type')?

yes, I think so

Copy link
Contributor

@carljm carljm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, sure. But with a TODO comment. Because with Charlie's metaclass PR, it should become something like:

Suggested change
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

Copy link
Contributor

@carljm carljm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very nice!

@sharkdp sharkdp force-pushed the david/issubclass-narrowing branch from 7787933 to 0884352 Compare November 7, 2024 10:27
@sharkdp sharkdp force-pushed the david/issubclass-narrowing branch from 7cc2599 to 400e101 Compare November 7, 2024 12:34
Copy link
Member

@AlexWaygood AlexWaygood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!

sharkdp and others added 4 commits November 7, 2024 13:45
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>
@sharkdp sharkdp merged commit f2546c5 into main Nov 7, 2024
@sharkdp sharkdp deleted the david/issubclass-narrowing branch November 7, 2024 13:15
Comment on lines +547 to +553
) if self_class
.metaclass(db)
.into_class_literal()
.map(|meta| meta.class.is_subclass_of(db, target_class))
.unwrap_or(false) =>
{
true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +1370 to +1375
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(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[red-knot] Type narrowing for issubclass tests

4 participants