8000 Simplify and tighten type aliases by ilevkivskyi · Pull Request #3524 · python/mypy · GitHub
[go: up one dir, main page]

Skip to content

Simplify and tighten type aliases #3524

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

Merged
merged 18 commits into from
Jul 7, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Second part of review comments
  • Loading branch information
ilevkivskyi committed Jul 6, 2017
commit 7e7c1b70e1cfff4f09e200bc2d3b298497891239
2 changes: 0 additions & 2 deletions mypy/fixup.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,6 @@ def visit_symbol_table(self, symtab: SymbolTable) -> None:
if stnode is not None:
value.node = stnode.node
value.type_override = stnode.type_override
if not value.type_override and self.quick_and_dirty:
value.type_override = Instance(stale_info(), [])
value.alias_tvars = stnode.alias_tvars or []
elif not self.quick_and_dirty:
assert stnode is not None, "Could not find cross-ref %s" % (cross_ref,)
Expand Down
2 changes: 2 additions & 0 deletions mypy/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2268,6 +2268,8 @@ class SymbolTableNode:
mod_id = '' # type: Optional[str]
# If this not None, override the type of the 'node' attribute.
type_override = None # type: Optional[mypy.types.Type]
# For generic aliases this stores the (qualified) names of type variables.
# (For example see testGenericAliasWithTypeVarsFromDifferentModules.)
alias_tvars = None # type: Optional[List[str]]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Add comment.

Are these short or full names? If short ones, it would be more correct to have full names. For example, a.T and b.T could refer to different type variables -- this is very unlikely, though.

Copy link
Member Author

Choose a reason for hiding this comment

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

It looks like these are qualified names. I added a test for this, and a comment here.

# If False, this name won't be imported via 'from <module> import *'.
# This has no effect on names within classes.
Expand Down
19 changes: 16 additions & 3 deletions mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -1626,6 +1626,11 @@ def alias_fallback(self, tp: Type) -> Instance:

def analyze_alias(self, rvalue: Expression,
allow_unnormalized: bool) -> Tuple[Optional[Type], List[str]]:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Add docstring. Explain arguments and the return value.

"""Check if 'rvalue' represents a valid type allowed for aliasing
(e.g. not a type variable). If yes, return the corresponding type and a list of
qualified type variable names for generic aliases.
If 'allow_unnormalized' is True, allow types like builtins.list[T].
"""
res = analyze_type_alias(rvalue,
self.lookup_qualified,
self.lookup_fully_qualified,
Expand All @@ -1643,9 +1648,13 @@ def analyze_alias(self, rvalue: Expression,
return res, alias_tvars

def check_and_set_up_type_alias(self, s: AssignmentStmt) -> None:
"""Check if assignment creates a type alias and set it up as needed."""
# Type aliases are created only at module scope, at class and function scopes
# assignments create class valued members and local variables with type object types.
"""Check if assignment creates a type alias and set it up as needed.
For simple aliases like L = List we use a simpler mechanism, just copying TypeInfo.
For subscripted (including generic) aliases we mark corresponding node as TYPE_ALIAS
and store the corresponding type in node.override and in rvalue.analyzed.
"""
# Type aliases are created only at module scope and class scope (for subscripted types),
# at function scope assignments always create local variables with type object types.
if (len(s.lvalues) == 1 and not self.is_func_scope() and
not (self.type and isinstance(s.rvalue, NameExpr) and s.lvalues[0].is_def)
and not s.type):
Expand All @@ -1668,6 +1677,8 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> None:
# so we need to replace it with non-explicit Anys
res = make_any_non_explicit(res)
if isinstance(res, Instance) and not res.args and isinstance(rvalue, RefExpr):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Add comment that describes the purpose of this special case.

# For simple (on-generic) aliases we use aliasing TypeInfo's
# to allow using them in runtime context where it makes sense.
node.node = res.type
if isinstance(rvalue, RefExpr):
sym = self.lookup_type_node(rvalue)
Expand All @@ -1678,6 +1689,8 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> None:
node.type_override = res
node.alias_tvars = alias_tvars
if isinstance(s.rvalue, IndexExpr):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Add comment that explains the motivation of this if statement.

# We only need this for subscripted aliases, since simple aliases
# are already processed using aliasing TypeInfo's above.
s.rvalue.analyzed = TypeAliasExpr(res, node.alias_tvars,
fallback=self.alias_fallback(res))
s.rvalue.analyzed.line = s.rvalue.line
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-generics.test
Original file line number Diff line number Diff line change
Expand Up @@ -935,7 +935,7 @@ from typing import TypeVar, List, Tuple
import a
import b
T = TypeVar('T')
Alias = List[Tuple[T, a.T, b.T, b.B.T]]
Alias = List[Tuple[T, a.T, b.T, b.B.T]] # alias_tvars here will be ['T', 'a.T', 'b.T', 'b.B.T']

[file a.py]
from typing import TypeVar
Expand Down
0