Skip to content

Fix TypedDict subtyping #11670

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

97littleleaf11
Copy link
Collaborator

Description

Fixes #5593
Fixes #10024
Fixes #9827
Partially solves #10593 and #11644

This PR moves special cases (introduced by #2407 and #11236) in SubtypeVisitor.visit_instance to the end of the func and also adds support for TypedDictType.

Test Plan

A new test case [testTypedDictTempTestName] under the subtyping section of check-typeddict.test. However I don't have an idea about its name.

@97littleleaf11 97littleleaf11 requested a review from JukkaL December 6, 2021 13:58
Copy link
Collaborator

@JukkaL JukkaL left a comment

Choose a reason for hiding this comment

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

Unfortunately, I don't think that this fixes the root cause, but is hiding the symptoms of another bug.

right_fallback = mypy.typeops.try_getting_instance_fallback(right)
if (right_fallback is not None
and ((isinstance(right, TupleType) and right_fallback.type.is_enum)
or isinstance(right, TypedDictType))):
Copy link
Collaborator

Choose a reason for hiding this comment

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

IIRC the fallback of a TypedDict type is actually not a "real" type, but a sort of implementation artifact. I believe that the actual bug is that we leak the fallback as an instance type. In particular, it shouldn't be possible to bind a TypedDict type to Type[T], since a TypedDict type is not a real class, and doesn't support isinstance, among other things. I suspect that is where things go wrong, and this change would be just papering over the root cause. I'm not 100% sure what is going on here, though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

the actual bug is that we leak the fallback as an instance type

Yes you're right. I am confused by Type[T] before and I just saw #9773 and other related discussions. If my understanding is correct, these issues should be fiexd by two steps: 1. throw errows when binding a TypedDict to Type[T]. 2. implement TypeForm[t] to support the original design pattern described in those issues.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

oops, I still need some extra investigation to catch up disscussions on Type[T] and TypeForm. It'd be great if you could provide some suggestions on implementation since it's a quite common issue.

def fun(c: C):
pass

fun(foo(C))
Copy link
Collaborator

Choose a reason for hiding this comment

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

The call foo(C) should actually generate an error (see my other comment). For example, if the call would make sense, we should handle cases like these, which probably won't work correctly right now:

d = foo(C)
d['x'] = 1  # Should be ok
d['y'] = 1  # Should be an error
d['x'] = 'x'  # Should be an error

@97littleleaf11 97littleleaf11 deleted the Fix-TypedDict-subtyping branch February 22, 2022 08:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants