-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Add machinery for marking places we subvert the type system #5467
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
Changes from 1 commit
5e21f6a
35af440
049d88c
07caba8
e29c39c
838178d
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 |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| """A Bogus[T] type alias for marking when we subvert the type system | ||
| We need this for compiling with mypyc, which inserts runtime | ||
| typechecks that cause problems when we subvert the type system. So | ||
| when compiling with mypyc, we turn those places into Any, while | ||
| keeping the types around for normal typechecks. | ||
| Since this causes the runtype types to be Any, this is best used | ||
| in places where efficient access to properties is not important. | ||
| For those cases some other technique should be used. | ||
| """ | ||
|
|
||
| from mypy_extensions import FlexibleAlias | ||
| from typing import TypeVar, Any | ||
|
|
||
| T = TypeVar('T') | ||
|
|
||
| SUPPRESS_BOGUS_TYPES = False | ||
| if SUPPRESS_BOGUS_TYPES: | ||
| Bogus = FlexibleAlias[T, Any] | ||
| else: | ||
| Bogus = FlexibleAlias[T, T] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,8 @@ | |
| from mypy.util import short_type | ||
| from mypy.visitor import NodeVisitor, StatementVisitor, ExpressionVisitor | ||
|
|
||
| from mypy.bogus_type import Bogus | ||
|
|
||
|
|
||
| class Context: | ||
| """Base type for objects that are valid as error message locations.""" | ||
|
|
@@ -174,10 +176,10 @@ class SymbolNode(Node): | |
| # TODO do not use methods for these | ||
|
|
||
| @abstractmethod | ||
| def name(self) -> str: pass | ||
| def name(self) -> Bogus[str]: pass | ||
|
||
|
|
||
| @abstractmethod | ||
| def fullname(self) -> str: pass | ||
| def fullname(self) -> Bogus[str]: pass | ||
|
|
||
| @abstractmethod | ||
| def serialize(self) -> JsonDict: pass | ||
|
|
@@ -195,9 +197,9 @@ class MypyFile(SymbolNode): | |
| """The abstract syntax tree of a single source file.""" | ||
|
|
||
| # Module name ('__main__' for initial file) | ||
| _name = None # type: str | ||
| _name = None # type: Bogus[str] | ||
| # Fully qualified module name | ||
| _fullname = None # type: str | ||
| _fullname = None # type: Bogus[str] | ||
|
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. I meant actually setting these two in
Collaborator
Author
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 doable but would require changing some types around and threading the module name into part of the parser where it isn't. Doesn't seem to be an advantage over patching up
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. OK.
Collaborator
Author
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. Though fixing |
||
| # Path to the file (None if not known) | ||
| path = '' | ||
| # Top-level definitions and statements | ||
|
|
@@ -236,10 +238,10 @@ def __init__(self, | |
| else: | ||
| self.ignored_lines = set() | ||
|
|
||
| def name(self) -> str: | ||
| def name(self) -> Bogus[str]: | ||
|
||
| return self._name | ||
|
|
||
| def fullname(self) -> str: | ||
| def fullname(self) -> Bogus[str]: | ||
| return self._fullname | ||
|
|
||
| def accept(self, visitor: NodeVisitor[T]) -> T: | ||
|
|
@@ -404,12 +406,12 @@ def __init__(self) -> None: | |
| self.is_static = False | ||
| # Name with module prefix | ||
| # TODO: Type should be Optional[str] | ||
| self._fullname = cast(str, None) | ||
| self._fullname = cast(Bogus[str], None) | ||
|
|
||
| @abstractmethod | ||
| def name(self) -> str: pass | ||
|
|
||
| def fullname(self) -> str: | ||
| def fullname(self) -> Bogus[str]: | ||
| return self._fullname | ||
|
|
||
|
|
||
|
|
@@ -660,7 +662,7 @@ def __init__(self, func: FuncDef, decorators: List[Expression], | |
| def name(self) -> str: | ||
| return self.func.name() | ||
|
|
||
| def fullname(self) -> str: | ||
| def fullname(self) -> Bogus[str]: | ||
| return self.func.fullname() | ||
|
|
||
| @property | ||
|
|
@@ -725,7 +727,7 @@ def __init__(self, name: str, type: 'Optional[mypy.types.Type]' = None) -> None: | |
| super().__init__() | ||
| self._name = name # Name without module prefix | ||
| # TODO: Should be Optional[str] | ||
| self._fullname = cast(str, None) # Name with module prefix | ||
| self._fullname = cast(Bogus[str], None) # Name with module prefix | ||
| # TODO: Should be Optional[TypeInfo] | ||
| self.info = cast(TypeInfo, None) # Defining class (for member variables) | ||
| self.type = type # type: Optional[mypy.types.Type] # Declared or inferred type, or None | ||
|
|
@@ -748,7 +750,7 @@ def __init__(self, name: str, type: 'Optional[mypy.types.Type]' = None) -> None: | |
| def name(self) -> str: | ||
| return self._name | ||
|
|
||
| def fullname(self) -> str: | ||
| def fullname(self) -> Bogus[str]: | ||
| return self._fullname | ||
|
|
||
| def accept(self, visitor: StatementVisitor[T]) -> T: | ||
|
|
@@ -780,7 +782,7 @@ class ClassDef(Statement): | |
| """Class definition""" | ||
|
|
||
| name = None # type: str # Name of the class without module prefix | ||
| fullname = None # type: str # Fully qualified name of the class | ||
| fullname = None # type: Bogus[str] # Fully qualified name of the class | ||
| defs = None # type: Block | ||
| type_vars = None # type: List[mypy.types.TypeVarDef] | ||
| # Base class expressions (not semantically analyzed -- can be arbitrary expressions) | ||
|
|
@@ -2054,7 +2056,7 @@ class is generic then it will be a type constructor of higher kind. | |
| the appropriate number of arguments. | ||
| """ | ||
|
|
||
| _fullname = None # type: str # Fully qualified name | ||
| _fullname = None # type: Bogus[str] # Fully qualified name | ||
| # Fully qualified name for the module this type was defined in. This | ||
| # information is also in the fullname, but is harder to extract in the | ||
| # case of nested class definitions. | ||
|
|
@@ -2195,7 +2197,7 @@ def name(self) -> str: | |
| """Short name.""" | ||
| return self.defn.name | ||
|
|
||
| def fullname(self) -> str: | ||
| def fullname(self) -> Bogus[str]: | ||
| return self._fullname | ||
|
|
||
| def is_generic(self) -> bool: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,7 @@ | |
| ) | ||
| from mypy.sharedparse import argument_elide_name | ||
| from mypy.util import IdMapper | ||
| from mypy.bogus_type import Bogus | ||
|
|
||
| T = TypeVar('T') | ||
|
|
||
|
|
@@ -341,8 +342,8 @@ def accept(self, visitor: 'TypeVisitor[T]') -> T: | |
| return visitor.visit_any(self) | ||
|
|
||
| def copy_modified(self, | ||
| type_of_any: TypeOfAny = _dummy, | ||
| original_any: Optional['AnyType'] = _dummy, | ||
| type_of_any: Bogus[TypeOfAny] = _dummy, | ||
| original_any: Bogus[Optional['AnyType']] = _dummy, | ||
|
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. Maybe add also a short comment about |
||
| ) -> 'AnyType': | ||
| if type_of_any is _dummy: | ||
| type_of_any = self.type_of_any | ||
|
|
@@ -743,22 +744,22 @@ def __init__(self, | |
| self.def_extras = {} | ||
|
|
||
| def copy_modified(self, | ||
| arg_types: List[Type] = _dummy, | ||
| arg_kinds: List[int] = _dummy, | ||
| arg_names: List[Optional[str]] = _dummy, | ||
| ret_type: Type = _dummy, | ||
| fallback: Instance = _dummy, | ||
| name: Optional[str] = _dummy, | ||
| definition: SymbolNode = _dummy, | ||
| variables: List[TypeVarDef] = _dummy, | ||
| line: int = _dummy, | ||
| column: int = _dummy, | ||
| is_ellipsis_args: bool = _dummy, | ||
| implicit: bool = _dummy, | ||
| special_sig: Optional[str] = _dummy, | ||
| from_type_type: bool = _dummy, | ||
| bound_args: List[Optional[Type]] = _dummy, | ||
| def_extras: Dict[str, Any] = _dummy) -> 'CallableType': | ||
| arg_types: Bogus[List[Type]] = _dummy, | ||
| arg_kinds: Bogus[List[int]] = _dummy, | ||
| arg_names: Bogus[List[Optional[str]]] = _dummy, | ||
| ret_type: Bogus[Type] = _dummy, | ||
| fallback: Bogus[Instance] = _dummy, | ||
| name: Bogus[Optional[str]] = _dummy, | ||
| definition: Bogus[SymbolNode] = _dummy, | ||
| variables: Bogus[List[TypeVarDef]] = _dummy, | ||
| line: Bogus[int] = _dummy, | ||
| column: Bogus[int] = _dummy, | ||
| is_ellipsis_args: Bogus[bool] = _dummy, | ||
| implicit: Bogus[bool] = _dummy, | ||
| special_sig: Bogus[Optional[str]] = _dummy, | ||
| from_type_type: Bogus[bool] = _dummy, | ||
| bound_args: Bogus[List[Optional[Type]]] = _dummy, | ||
| def_extras: Bogus[Dict[str, Any]] = _dummy) -> 'CallableType': | ||
| return CallableType( | ||
| arg_types=arg_types if arg_types is not _dummy else self.arg_types, | ||
| arg_kinds=arg_kinds if arg_kinds is not _dummy else self.arg_kinds, | ||
|
|
@@ -1457,8 +1458,9 @@ class TypeType(Type): | |
| # a generic class instance, a union, Any, a type variable... | ||
| item = None # type: Type | ||
|
|
||
| def __init__(self, item: Union[Instance, AnyType, TypeVarType, TupleType, NoneTyp, | ||
| CallableType], *, line: int = -1, column: int = -1) -> None: | ||
| def __init__(self, item: Bogus[Union[Instance, AnyType, TypeVarType, TupleType, NoneTyp, | ||
| CallableType]], *, | ||
| line: int = -1, column: int = -1) -> None: | ||
|
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. I am a bit surprised the
Collaborator
Author
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. The crash does indeed happen in |
||
| """To ensure Type[Union[A, B]] is always represented as Union[Type[A], Type[B]], item of | ||
| type UnionType must be handled through make_normalized static method. | ||
| """ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| [mypy] | ||
| disallow_untyped_defs = True | ||
| disallow_subclassing_any = True | ||
| warn_no_return = True | ||
| strict_optional = True | ||
| no_implicit_optional = True | ||
| disallow_any_generics = True | ||
| disallow_any_unimported = True | ||
| warn_redundant_casts = True | ||
| warn_unused_configs = True | ||
| always_true = SUPPRESS_BOGUS_TYPES | ||
|
|
||
| # needs py2 compatibility | ||
| [mypy-mypy.test.testextensions] | ||
| disallow_untyped_defs = False |
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.
runtype -> runtime?