Fix crash with PartialTypes and the enum plugin #14021
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #12109.
The original issue reported that the bug had to do with the use of the
--follow-imports=skip
flag. However, it turned out this was a red herring after closer inspection: I was able to trigger a more minimal repro both with and without this flag:The first two
reveal_types
demonstrate the crux of the bug: the enum plugin does not correctly handle and convert partial types into regular types when inferring the type of the.value
field.This can then cause any number of downstream problems. For example, suppose we modify
def check(...)
so it runsreveal_type(self.value)
. Doing this will trigger a crash in mypy because it makes the enum plugin eventually try runningis_equivalent(...)
on the two partial types. Butis_equivalent
does not support partial types, so we crash.I opted to solve this problem by:
Making the enum plugin explicitly call the
fixup_partial_types
function on all field types. This prevents the code from crashing.Modifies mypy so that Final vars are never marked as being PartialTypes. Without this,
reveal_type(Foo.b.value)
would report a type ofUnion[Any, None]
instead of justNone
. (Note that all enum fields are implicitly final).(Explain how this PR changes mypy.)