-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Type[C] #1569
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
Type[C] #1569
Changes from all commits
b7ddf36
eb61f1d
7b52ac6
1fd14f0
371e425
96696ff
aa37595
d4745b0
cf4a0b7
81ee239
3d92049
5ab11d2
afb0482
db30d59
6029c9d
786ef96
ef247f2
4162103
26ff267
256b31a
d224aff
d9c74a0
eaa9e0d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,7 @@ | |
from mypy.types import ( | ||
Type, AnyType, CallableType, Overloaded, NoneTyp, Void, TypeVarDef, | ||
TupleType, Instance, TypeVarType, ErasedType, UnionType, | ||
PartialType, DeletedType, UnboundType | ||
PartialType, DeletedType, UnboundType, TypeType | ||
) | ||
from mypy.nodes import ( | ||
NameExpr, RefExpr, Var, FuncDef, OverloadedFuncDef, TypeInfo, CallExpr, | ||
|
@@ -277,9 +277,49 @@ def check_call(self, callee: Type, args: List[Node], | |
elif isinstance(callee, TypeVarType): | ||
return self.check_call(callee.upper_bound, args, arg_kinds, context, arg_names, | ||
callable_node, arg_messages) | ||
elif isinstance(callee, TypeType): | ||
# Pass the original Type[] as context since that's where errors should go. | ||
item = self.analyze_type_type_callee(callee.item, callee) | ||
return self.check_call(item, args, arg_kinds, context, arg_names, | ||
callable_node, arg_messages) | ||
else: | ||
return self.msg.not_callable(callee, context), AnyType() | ||
|
||
def analyze_type_type_callee(self, item: Type, context: Context) -> Type: | ||
"""Analyze the callee X in X(...) where X is Type[item]. | ||
|
||
Return a Y that we can pass to check_call(Y, ...). | ||
""" | ||
if isinstance(item, AnyType): | ||
return AnyType() | ||
if isinstance(item, Instance): | ||
return type_object_type(item.type, self.named_type) | ||
if isinstance(item, UnionType): | ||
return UnionType([self.analyze_type_type_callee(item, context) | ||
for item in item.items], item.line) | ||
if isinstance(item, TypeVarType): | ||
# Pretend we're calling the typevar's upper bound, | ||
# i.e. its constructor (a poor approximation for reality, | ||
# but better than AnyType...), but replace the return type | ||
# with typevar. | ||
callee = self.analyze_type_type_callee(item.upper_bound, context) | ||
if isinstance(callee, CallableType): | ||
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. This could also be |
||
if callee.is_generic(): | ||
callee = None | ||
else: | ||
callee = callee.copy_modified(ret_type=item) | ||
elif isinstance(callee, Overloaded): | ||
if callee.items()[0].is_generic(): | ||
callee = None | ||
else: | ||
callee = Overloaded([c.copy_modified(ret_type=item) | ||
for c in callee.items()]) | ||
if callee: | ||
return callee | ||
|
||
self.msg.unsupported_type_type(item, context) | ||
return AnyType() | ||
|
||
def infer_arg_types_in_context(self, callee: CallableType, | ||
args: List[Node]) -> List[Type]: | ||
"""Infer argument expression types using a callable type as context. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ | |
from mypy.types import ( | ||
Type, Instance, CallableType, TypeVisitor, UnboundType, ErrorType, AnyType, | ||
Void, NoneTyp, TypeVarType, Overloaded, TupleType, UnionType, ErasedType, TypeList, | ||
PartialType, DeletedType | ||
PartialType, DeletedType, TypeType | ||
) | ||
|
||
|
||
|
@@ -94,6 +94,13 @@ def visit_union_type(self, t: UnionType) -> Type: | |
def visit_partial_type(self, t: PartialType) -> Type: | ||
return t | ||
|
||
def visit_type_type(self, t: TypeType) -> Type: | ||
# TODO: Verify that the new item type is valid (instance or | ||
# union of instances or Any). Sadly we can't report errors | ||
# here yet. | ||
item = t.item.accept(self) | ||
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. I suspect that we should verify here that the new item type is valid (instance or union of instances, or |
||
return TypeType(item) | ||
|
||
def expand_types(self, types: List[Type]) -> List[Type]: | ||
a = [] # type: List[Type] | ||
for t in types: | ||
|
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.
If the class is generic things get harder. Not sure what we should then, though. Maybe just reject calls to generic type objects for now.