Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 3.3k
Generic type aliases#2378
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
Uh oh!
There was an error while loading. Please reload this page.
Generic type aliases #2378
Changes from all commits
5dc0090f6d862bb0790d47ddd6ab633e3d107baa5156b7ae7cbcb2c05c92b1213e1fffee1c25c2edcf4864fc96e8c64111c106204feb9413d402a688cea156382c53e863c576544ff66File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -6,7 +6,8 @@ | ||
| Type, AnyType, CallableType, Overloaded, NoneTyp, Void, TypeVarDef, | ||
| TupleType, Instance, TypeVarId, TypeVarType, ErasedType, UnionType, | ||
| PartialType, DeletedType, UnboundType, UninhabitedType, TypeType, | ||
| true_only, false_only, is_named_instance, function_type | ||
| true_only, false_only, is_named_instance, function_type, | ||
| get_typ_args, set_typ_args, | ||
| ) | ||
| from mypy.nodes import ( | ||
| NameExpr, RefExpr, Var, FuncDef, OverloadedFuncDef, TypeInfo, CallExpr, | ||
| @@ -17,6 +18,7 @@ | ||
| ConditionalExpr, ComparisonExpr, TempNode, SetComprehension, | ||
| DictionaryComprehension, ComplexExpr, EllipsisExpr, StarExpr, | ||
| TypeAliasExpr, BackquoteExpr, ARG_POS, ARG_NAMED, ARG_STAR2, MODULE_REF, | ||
| UNBOUND_TVAR, BOUND_TVAR, | ||
| ) | ||
| from mypy import nodes | ||
| import mypy.checker | ||
| @@ -1375,8 +1377,55 @@ def visit_type_application(self, tapp: TypeApplication) -> Type: | ||
| return AnyType() | ||
| def visit_type_alias_expr(self, alias: TypeAliasExpr) -> Type: | ||
| """Get type of a type alias (could be generic) in a runtime expression.""" | ||
| item = alias.type | ||
| if not alias.in_runtime: | ||
| # We don't replace TypeVar's with Any for alias used as Alias[T](42). | ||
| item = self.replace_tvars_any(item) | ||
| if isinstance(item, Instance): | ||
| # Normally we get a callable type (or overloaded) with .is_type_obj() true | ||
| # representing the class's constructor | ||
| tp = type_object_type(item.type, self.named_type) | ||
| else: | ||
| # This type is invalid in most runtime contexts | ||
| # and corresponding an error will be reported. | ||
| return alias.fallback | ||
| if isinstance(tp, CallableType): | ||
| if len(tp.variables) != len(item.args): | ||
| self.msg.incompatible_type_application(len(tp.variables), | ||
| len(item.args), item) | ||
| return AnyType() | ||
| return self.apply_generic_arguments(tp, item.args, item) | ||
| elif isinstance(tp, Overloaded): | ||
| for it in tp.items(): | ||
| if len(it.variables) != len(item.args): | ||
| self.msg.incompatible_type_application(len(it.variables), | ||
| len(item.args), item) | ||
| return AnyType() | ||
| return Overloaded([self.apply_generic_arguments(it, item.args, item) | ||
| for it in tp.items()]) | ||
| return AnyType() | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not an error because we can only get here when there already was a previous error, right? MemberAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gvanrossum Yes, I think so. At least I don't see a way to get there without previously having an error. | ||
| def replace_tvars_any(self, tp: Type) -> Type: | ||
| """Replace all type variables of a type alias tp with Any. Basically, this function | ||
| finishes what could not be done in method TypeAnalyser.visit_unbound_type() | ||
| from typeanal.py. | ||
| """ | ||
| typ_args = get_typ_args(tp) | ||
| new_args = typ_args[:] | ||
| for i, arg in enumerate(typ_args): | ||
| if isinstance(arg, UnboundType): | ||
| sym = None | ||
| try: | ||
| sym = self.chk.lookup_qualified(arg.name) | ||
| except KeyError: | ||
| pass | ||
| if sym and (sym.kind == UNBOUND_TVAR or sym.kind == BOUND_TVAR): | ||
| new_args[i] = AnyType() | ||
| else: | ||
| new_args[i] = self.replace_tvars_any(arg) | ||
| return set_typ_args(tp, new_args, tp.line, tp.column) | ||
| def visit_list_expr(self, e: ListExpr) -> Type: | ||
| """Type check a list expression [...].""" | ||
| return self.check_lst_expr(e.items, 'builtins.list', '<list>', e) | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like a comment here explaining that we'll generally get a callable type (or overloaded) with .is_type_obj() true, representing the class's constructor. This would explain that below we really just check for callable and overloaded.