Skip to content

Catch incomplete TypeVisitor implementations #733

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

Closed
wants to merge 8 commits into from
2 changes: 1 addition & 1 deletion mypy/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ def lookup_state(self, module: str) -> 'State':
for state in self.states:
if state.id == module:
return state
raise RuntimeError('%s not found' % str)
raise RuntimeError('%s not found' % module)

def all_imported_modules_in_file(self,
file: MypyFile) -> List[Tuple[str, int]]:
Expand Down
6 changes: 6 additions & 0 deletions mypy/constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,12 @@ def infer_against_any(self, types: List[Type]) -> List[Constraint]:
res.extend(infer_constraints(t, AnyType(), self.direction))
return res

def visit_overloaded(self, type: Overloaded) -> List[Constraint]:
res = [] # type: List[Constraint]
for t in type.items():
res.extend(infer_constraints(t, self.actual, self.direction))
return res


def negate_constraints(constraints: List[Constraint]) -> List[Constraint]:
res = [] # type: List[Constraint]
Expand Down
9 changes: 8 additions & 1 deletion mypy/sametypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from mypy.types import (
Type, UnboundType, ErrorType, AnyType, NoneTyp, Void, TupleType, UnionType, CallableType,
TypeVarType, Instance, TypeVisitor, ErasedType, TypeList
TypeVarType, Instance, TypeVisitor, ErasedType, TypeList, Overloaded
)


Expand Down Expand Up @@ -91,3 +91,10 @@ def visit_union_type(self, left: UnionType) -> bool:
return is_same_types(left.items, cast(UnionType, self.right).items)
else:
return False

def visit_overloaded(self, left: Overloaded) -> bool:
if isinstance(self.right, Overloaded):
return is_same_types(cast(List[Type], left.items()),
cast(List[Type], cast(Overloaded, self.right).items()))
else:
return False
3 changes: 3 additions & 0 deletions mypy/typeanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,3 +333,6 @@ def visit_type_list(self, t: TypeList) -> None:

def visit_type_var(self, t: TypeVarType) -> None:
pass

def visit_star_type(self, t: StarType) -> None:
pass
34 changes: 28 additions & 6 deletions mypy/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,50 +492,65 @@ class TypeVisitor(Generic[T]):
The parameter T is the return type of the visit methods.
"""

def _notimplemented_helper(self) -> NotImplementedError:
return NotImplementedError("Method visit_type_list not implemented in "
+ "'{}'\n".format(type(self).__name__)
+ "This is a known bug, track development in "
+ "'https://github.com/JukkaL/mypy/issues/730'")

@abstractmethod
def visit_unbound_type(self, t: UnboundType) -> T:
pass

def visit_type_list(self, t: TypeList) -> T:
pass
raise self._notimplemented_helper()

def visit_error_type(self, t: ErrorType) -> T:
pass
raise self._notimplemented_helper()

@abstractmethod
def visit_any(self, t: AnyType) -> T:
pass

@abstractmethod
def visit_void(self, t: Void) -> T:
pass

@abstractmethod
def visit_none_type(self, t: NoneTyp) -> T:
pass

def visit_erased_type(self, t: ErasedType) -> T:
pass
raise self._notimplemented_helper()

@abstractmethod
def visit_type_var(self, t: TypeVarType) -> T:
pass

@abstractmethod
def visit_instance(self, t: Instance) -> T:
pass

@abstractmethod
def visit_callable_type(self, t: CallableType) -> T:
pass

def visit_overloaded(self, t: Overloaded) -> T:
pass
raise self._notimplemented_helper()

@abstractmethod
def visit_tuple_type(self, t: TupleType) -> T:
pass

def visit_star_type(self, t: StarType) -> T:
pass
raise self._notimplemented_helper()

@abstractmethod
def visit_union_type(self, t: UnionType) -> T:
pass

def visit_ellipsis_type(self, t: EllipsisType) -> T:
assert False # XXX catch visitors that don't have this implemented yet
raise self._notimplemented_helper()


class TypeTranslator(TypeVisitor[Type]):
Expand Down Expand Up @@ -609,6 +624,10 @@ def translate_variables(self,
variables: List[TypeVarDef]) -> List[TypeVarDef]:
return variables

def visit_overloaded(self, type: Overloaded) -> Type:
items = [t.accept(self) for t in type.items()] # type: ignore
return Overloaded(items=cast(List[CallableType], items))


class TypeStrVisitor(TypeVisitor[str]):
"""Visitor for pretty-printing types into strings.
Expand Down Expand Up @@ -805,6 +824,9 @@ def visit_star_type(self, t: StarType) -> bool:
def visit_union_type(self, t: UnionType) -> bool:
return self.query_types(t.items)

def visit_overloaded(self, t: Overloaded) -> bool:
return self.query_types(cast(List[Type], t.items()))

def query_types(self, types: List[Type]) -> bool:
"""Perform a query for a list of types.

Expand Down