python / mypy

Optional static typing for Python
https://www.mypy-lang.org/
Other
17.93k stars 2.75k forks source link

No error on new union syntax with union of fake types (`TypeAlias` and `None`) #11582

Open KotlinIsland opened 2 years ago

KotlinIsland commented 2 years ago
from typing import TypeAlias

AMONGUS: TypeAlias = "int"
IMPOSTER: TypeAlias = "str"

a: AMONGUS | IMPOSTER = 0  # SUS ALERT
b: AMONGUS | None = None  # SUS ALERT

Any types in a new union syntax that are fake(looking at you None) will be runtime errors.

sobolevn commented 2 years ago

Interesting case 🤔

Forward references are allowed in https://www.python.org/dev/peps/pep-0613/#forward-references

But, I think that AMONGUS | IMPOSTER should be an error in mypy in this case. We have to track what value was actually used for creating a type alias: real or forward ref. And when using new-style unions we can check that | operator is supported for these types.

sobolevn commented 2 years ago

This is quite hard to fix. Because AssignmentStmt does not have something like .annotation_expr.

Fields that are present at the moment: https://github.com/python/mypy/blob/b47245adc60eecde9164799c426f3bffcedbc48e/mypy/nodes.py#L1104-L1121

So, my plan is:

  1. Add annotation_expr field to AssignmentStmt, assign it during fastparse.py
  2. Analyze it by slightly different rules during semanal.py
  3. Type check this new expression in checker.py stage
  4. Probably I would need to also modify things like ast merger / differ, fixup, cache, etc

I am not going to touch anything related to .type or .unanalyzed_type, so it should be fine.

sobolevn commented 2 years ago

Moreover, we need to change how semanal binds types somehow for this case. Because we need to make sure that semanal understands that AMONGUS: TypeAlias = "int" is str, not TypeAlias[int] when analyzed as an annotation.

sobolevn commented 2 years ago

@KotlinIsland take a look at #11611

KotlinIsland commented 2 years ago

@sobolevn Looks good! but does that handle None (None and strs are the only two fake types that I know of). None | None currently is okay with mypy.