Repository: python/mypy

Issue:
Not all types and nodes have `__slots__`
For some reason not all classes in 
- `types.py` https://github.com/python/mypy/blob/master/mypy/types.py
- `nodes.py` https://github.com/python/mypy/blob/master/mypy/nodes.py

have explicit `__slots__`.

I will send a PR with the fix.
Not all types and nodes have `__slots__`
For some reason not all classes in 
- `types.py` https://github.com/python/mypy/blob/master/mypy/types.py
- `nodes.py` https://github.com/python/mypy/blob/master/mypy/nodes.py

have explicit `__slots__`.

I will send a PR with the fix.


Discussion:

Resolving patch:
diff --git a/mypy/nodes.py b/mypy/nodes.py
--- a/mypy/nodes.py
+++ b/mypy/nodes.py
@@ -201,7 +201,8 @@ class FakeExpression(Expression):
     We need a dummy expression in one place, and can't instantiate Expression
     because it is a trait and mypyc barfs.
     """
-    pass
+
+    __slots__ = ()
 
 
 # TODO:
@@ -246,16 +247,20 @@ def deserialize(cls, data: JsonDict) -> 'SymbolNode':
 class MypyFile(SymbolNode):
     """The abstract syntax tree of a single source file."""
 
+    __slots__ = ('_fullname', 'path', 'defs', 'alias_deps',
+                 'is_bom', 'names', 'imports', 'ignored_lines', 'is_stub',
+                 'is_cache_skeleton', 'is_partial_stub_package', 'plugin_deps')
+
     # Fully qualified module name
     _fullname: Bogus[str]
     # Path to the file (empty string if not known)
-    path = ''
+    path: str
     # Top-level definitions and statements
     defs: List[Statement]
     # Type alias dependencies as mapping from target to set of alias full names
     alias_deps: DefaultDict[str, Set[str]]
     # Is there a UTF-8 BOM at the start?
-    is_bom = False
+    is_bom: bool
     names: "SymbolTable"
     # All import nodes within the file (also ones within functions etc.)
     imports: List["ImportBase"]
@@ -264,13 +269,13 @@ class MypyFile(SymbolNode):
     # error codes to ignore.
     ignored_lines: Dict[int, List[str]]
     # Is this file represented by a stub file (.pyi)?
-    is_stub = False
+    is_stub: bool
     # Is this loaded from the cache and thus missing the actual body of the file?
-    is_cache_skeleton = False
+    is_cache_skeleton: bool
     # Does this represent an __init__.pyi stub with a module __getattr__
     # (i.e. a partial stub package), for such packages we suppress any missing
     # module errors in addition to missing attribute errors.
-    is_partial_stub_package = False
+    is_partial_stub_package: bool
     # Plugin-created dependencies
     plugin_deps: Dict[str, Set[str]]
 
@@ -291,6 +296,11 @@ def __init__(self,
         else:
             self.ignored_lines = {}
 
+        self.path = ''
+        self.is_stub = False
+        self.is_cache_skeleton = False
+        self.is_partial_stub_package = False
+
     def local_definitions(self) -> Iterator[Definition]:
         """Return all definitions within the module (including nested).
 
@@ -337,9 +347,11 @@ def deserialize(cls, data: JsonDict) -> 'MypyFile':
 class ImportBase(Statement):
     """Base class for all import statements."""
 
-    is_unreachable = False  # Set by semanal.SemanticAnalyzerPass1 if inside `if False` etc.
-    is_top_level = False  # Ditto if outside any class or def
-    is_mypy_only = False  # Ditto if inside `if TYPE_CHECKING` or `if MYPY`
+    __slots__ = ('is_unreachable', 'is_top_level', 'is_mypy_only', 'assignments')
+
+    is_unreachable: bool  # Set by semanal.SemanticAnalyzerPass1 if inside `if False` etc.
+    is_top_level: bool  # Ditto if outside any class or def
+    is_mypy_only: bool  # Ditto if inside `if TYPE_CHECKING` or `if MYPY`
 
     # If an import replaces existing definitions, we construct dummy assignment
     # statements that assign the imported names to the names in the current scope,
@@ -352,11 +364,16 @@ class ImportBase(Statement):
     def __init__(self) -> None:
         super().__init__()
         self.assignments = []
+        self.is_unreachable = False
+        self.is_top_level = False
+        self.is_mypy_only = False
 
 
 class Import(ImportBase):
     """import m [as n]"""
 
+    __slots__ = ('ids',)
+
     ids: List[Tuple[str, Optional[str]]]  # (module id, as id)
 
     def __init__(self, ids: List[Tuple[str, Optional[str]]]) -> None:
@@ -370,6 +387,8 @@ def accept(self, visitor: StatementVisitor[T]) -> T:
 class ImportFrom(ImportBase):
     """from m import x [as y], ..."""
 
+    __slots__ = ('id', 'names', 'relative')
+
     id: str
     relative: int
     names: List[Tuple[str, Optional[str]]]  # Tuples (name, as name)
@@ -387,6 +406,8 @@ def accept(self, visitor: StatementVisitor[T]) -> T:
 class ImportAll(ImportBase):
     """from m import *"""
 
+    __slots__ = ('id', 'relative', 'imported_names')
+
     id: str
     relative: int
     # NOTE: Only filled and used by old semantic analyzer.
@@ -414,6 +435,8 @@ class ImportedName(SymbolNode):
     can't be visited.
     """
 
+    __slots__ = ('target_fullname',)
+
     def __init__(self, target_fullname: str) -> None:
         super().__init__()
         self.target_fullname = target_fullname
@@ -504,9 +527,11 @@ class OverloadedFuncDef(FuncBase, SymbolNode, Statement):
     Overloaded variants must be consecutive in the source file.
     """
 
+    __slots__ = ('items', 'unanalyzed_items', 'impl')
+
     items: List[OverloadPart]
     unanalyzed_items: List[OverloadPart]
-    impl: Optional[OverloadPart] = None
+    impl: Optional[OverloadPart]
 
     def __init__(self, items: List['OverloadPart']) -> None:
         super().__init__()
@@ -745,13 +770,15 @@ class Decorator(SymbolNode, Statement):
     A single Decorator object can include any number of function decorators.
     """
 
+    __slots__ = ('func', 'decorators', 'original_decorators', 'var', 'is_overload')
+
     func: FuncDef  # Decorated function
     decorators: List[Expression]  # Decorators (may be empty)
     # Some decorators are removed by semanal, keep the original here.
     original_decorators: List[Expression]
     # TODO: This is mostly used for the type; consider replacing with a 'type' attribute
     var: "Var"  # Represents the decorated function obj
-    is_overload = False
+    is_overload: bool
 
     def __init__(self, func: FuncDef, decorators: List[Expression],
                  var: 'Var') -> None:
@@ -922,8 +949,13 @@ def deserialize(cls, data: JsonDict) -> 'Var':
 
 class ClassDef(Statement):
     """Class definition"""
+
+    __slots__ = ('name', 'fullname', 'defs', 'type_vars', 'base_type_exprs',
+                 'removed_base_type_exprs', 'info', 'metaclass', 'decorators',
+                 'keywords', 'analyzed', 'has_incompatible_baseclass')
+
     name: str  # Name of the class without module prefix
-    fullname: Bogus[str] = None  # type: ignore # Fully qualified name of the class
+    fullname: Bogus[str]  # Fully qualified name of the class
     defs: "Block"
     type_vars: List["mypy.types.TypeVarType"]
     # Base class expressions (not semantically analyzed -- can be arbitrary expressions)
@@ -931,11 +963,11 @@ class ClassDef(Statement):
     # Special base classes like Generic[...] get moved here during semantic analysis
     removed_base_type_exprs: List[Expression]
     info: "TypeInfo"  # Related TypeInfo
-    metaclass: Optional[Expression] = None
+    metaclass: Optional[Expression]
     decorators: List[Expression]
     keywords: "OrderedDict[str, Expression]"
-    analyzed: Optional[Expression] = None
-    has_incompatible_baseclass = False
+    analyzed: Optional[Expression]
+    has_incompatible_baseclass: bool
 
     def __init__(self,
                  name: str,
@@ -946,6 +978,7 @@ def __init__(self,
                  keywords: Optional[List[Tuple[str, Expression]]] = None) -> None:
         super().__init__()
         self.name = name
+        self.fullname = None  # type: ignore
         self.defs = defs
         self.type_vars = type_vars or []
         self.base_type_exprs = base_type_exprs or []
@@ -954,6 +987,8 @@ def __init__(self,
         self.metaclass = metaclass
         self.decorators = []
         self.keywords = OrderedDict(keywords or [])
+        self.analyzed = None
+        self.has_incompatible_baseclass = False
 
     def accept(self, visitor: StatementVisitor[T]) -> T:
         return visitor.visit_class_def(self)
@@ -984,6 +1019,8 @@ def deserialize(self, data: JsonDict) -> 'ClassDef':
 class GlobalDecl(Statement):
     """Declaration global x, y, ..."""
 
+    __slots__ = ('names',)
+
     names: List[str]
 
     def __init__(self, names: List[str]) -> None:
@@ -997,6 +1034,8 @@ def accept(self, visitor: StatementVisitor[T]) -> T:
 class NonlocalDecl(Statement):
     """Declaration nonlocal x, y, ..."""
 
+    __slots__ = ('names',)
+
     names: List[str]
 
     def __init__(self, names: List[str]) -> None:
@@ -1030,6 +1069,8 @@ def accept(self, visitor: StatementVisitor[T]) -> T:
 class ExpressionStmt(Statement):
     """An expression as a statement, such as print(s)."""
 
+    __slots__ = ('expr',)
+
     expr: Expression
 
     def __init__(self, expr: Expression) -> None:
@@ -1051,24 +1092,27 @@ class AssignmentStmt(Statement):
     An lvalue can be NameExpr, TupleExpr, ListExpr, MemberExpr, or IndexExpr.
     """
 
+    __slots__ = ('lvalues', 'rvalue', 'type', 'unanalyzed_type', 'new_syntax',
+                 'is_alias_def', 'is_final_def')
+
     lvalues: List[Lvalue]
     # This is a TempNode if and only if no rvalue (x: t).
     rvalue: Expression
     # Declared type in a comment, may be None.
-    type: Optional["mypy.types.Type"] = None
+    type: Optional["mypy.types.Type"]
     # Original, not semantically analyzed type in annotation (used for reprocessing)
-    unanalyzed_type: Optional["mypy.types.Type"] = None
+    unanalyzed_type: Optional["mypy.types.Type"]
     # This indicates usage of PEP 526 type annotation syntax in assignment.
-    new_syntax: bool = False
+    new_syntax: bool
     # Does this assignment define a type alias?
-    is_alias_def = False
+    is_alias_def: bool
     # Is this a final definition?
     # Final attributes can't be re-assigned once set, and can't be overridden
     # in a subclass. This flag is not set if an attempted declaration was found to
     # be invalid during semantic analysis. It is still set to `True` if
     # a final declaration overrides another final declaration (this is checked
     # during type checking when MROs are known).
-    is_final_def = False
+    is_final_def: bool
 
     def __init__(self, lvalues: List[Lvalue], rvalue: Expression,
                  type: 'Optional[mypy.types.Type]' = None, new_syntax: bool = False) -> None:
@@ -1078,6 +1122,8 @@ def __init__(self, lvalues: List[Lvalue], rvalue: Expression,
         self.type = type
         self.unanalyzed_type = type
         self.new_syntax = new_syntax
+        self.is_alias_def = False
+        self.is_final_def = False
 
     def accept(self, visitor: StatementVisitor[T]) -> T:
         return visitor.visit_assignment_stmt(self)
@@ -1086,7 +1132,9 @@ def accept(self, visitor: StatementVisitor[T]) -> T:
 class OperatorAssignmentStmt(Statement):
     """Operator assignment statement such as x += 1"""
 
-    op = ''
+    __slots__ = ('op', 'lvalue', 'rvalue')
+
+    op: str  # TODO: Enum?
     lvalue: Lvalue
     rvalue: Expression
 
@@ -1101,9 +1149,11 @@ def accept(self, visitor: StatementVisitor[T]) -> T:
 
 
 class WhileStmt(Statement):
+    __slots__ = ('expr', 'body', 'else_body')
+
     expr: Expression
     body: Block
-    else_body: Optional[Block] = None
+    else_body: Optional[Block]
 
     def __init__(self, expr: Expression, body: Block, else_body: Optional[Block]) -> None:
         super().__init__()
@@ -1116,21 +1166,25 @@ def accept(self, visitor: StatementVisitor[T]) -> T:
 
 
 class ForStmt(Statement):
+    __slots__ = ('index', 'index_type', 'unanalyzed_index_type',
+                 'inferred_item_type', 'inferred_iterator_type',
+                 'expr', 'body', 'else_body', 'is_async')
+
     # Index variables
     index: Lvalue
     # Type given by type comments for index, can be None
-    index_type: Optional["mypy.types.Type"] = None
+    index_type: Optional["mypy.types.Type"]
     # Original, not semantically analyzed type in annotation (used for reprocessing)
-    unanalyzed_index_type: Optional["mypy.types.Type"] = None
+    unanalyzed_index_type: Optional["mypy.types.Type"]
     # Inferred iterable item type
-    inferred_item_type: Optional["mypy.types.Type"] = None
+    inferred_item_type: Optional["mypy.types.Type"]
     # Inferred iterator type
-    inferred_iterator_type: Optional["mypy.types.Type"] = None
+    inferred_iterator_type: Optional["mypy.types.Type"]
     # Expression to iterate
     expr: Expression
     body: Block
-    else_body: Optional[Block] = None
-    is_async = False  # True if `async for ...` (PEP 492, Python 3.5)
+    else_body: Optional[Block]
+    is_async: bool  # True if `async for ...` (PEP 492, Python 3.5)
 
     def __init__(self,
                  index: Lvalue,
@@ -1142,16 +1196,21 @@ def __init__(self,
         self.index = index
         self.index_type = index_type
         self.unanalyzed_index_type = index_type
+        self.inferred_item_type = None
+        self.inferred_iterator_type = None
         self.expr = expr
         self.body = body
         self.else_body = else_body
+        self.is_async = False
 
     def accept(self, visitor: StatementVisitor[T]) -> T:
         return visitor.visit_for_stmt(self)
 
 
 class ReturnStmt(Statement):
-    expr: Optional[Expression] = None
+    __slots__ = ('expr',)
+
+    expr: Optional[Expression]
 
     def __init__(self, expr: Optional[Expression]) -> None:
         super().__init__()
@@ -1162,8 +1221,10 @@ def accept(self, visitor: StatementVisitor[T]) -> T:
 
 
 class AssertStmt(Statement):
+    __slots__ = ('expr', 'msg')
+
     expr: Expression
-    msg: Optional[Expression] = None
+    msg: Optional[Expression]
 
     def __init__(self, expr: Expression, msg: Optional[Expression] = None) -> None:
         super().__init__()
@@ -1175,6 +1236,8 @@ def accept(self, visitor: StatementVisitor[T]) -> T:
 
 
 class DelStmt(Statement):
+    __slots__ = ('expr',)
+
     expr: Lvalue
 
     def __init__(self, expr: Lvalue) -> None:
@@ -1186,24 +1249,32 @@ def accept(self, visitor: StatementVisitor[T]) -> T:
 
 
 class BreakStmt(Statement):
+    __slots__ = ()
+
     def accept(self, visitor: StatementVisitor[T]) -> T:
         return visitor.visit_break_stmt(self)
 
 
 class ContinueStmt(Statement):
+    __slots__ = ()
+
     def accept(self, visitor: StatementVisitor[T]) -> T:
         return visitor.visit_continue_stmt(self)
 
 
 class PassStmt(Statement):
+    __slots__ = ()
+
     def accept(self, visitor: StatementVisitor[T]) -> T:
         return visitor.visit_pass_stmt(self)
 
 
 class IfStmt(Statement):
+    __slots__ = ('expr', 'body', 'else_body')
+
     expr: List[Expression]
     body: List[Block]
-    else_body: Optional[Block] = None
+    else_body: Optional[Block]
 
     def __init__(self, expr: List[Expression], body: List[Block],
                  else_body: Optional[Block]) -> None:
@@ -1217,9 +1288,11 @@ def accept(self, visitor: StatementVisitor[T]) -> T:
 
 
 class RaiseStmt(Statement):
+    __slots__ = ('expr', 'from_expr')
+
     # Plain 'raise' is a valid statement.
-    expr: Optional[Expression] = None
-    from_expr: Optional[Expression] = None
+    expr: Optional[Expression]
+    from_expr: Optional[Expression]
 
     def __init__(self, expr: Optional[Expression], from_expr: Optional[Expression]) -> None:
         super().__init__()
@@ -1231,13 +1304,15 @@ def accept(self, visitor: StatementVisitor[T]) -> T:
 
 
 class TryStmt(Statement):
+    __slots__ = ('body', 'types', 'vars', 'handlers', 'else_body', 'finally_body')
+
     body: Block  # Try body
     # Plain 'except:' also possible
     types: List[Optional[Expression]]  # Except type expressions
     vars: List[Optional["NameExpr"]]  # Except variable names
     handlers: List[Block]  # Except bodies
-    else_body: Optional[Block] = None
-    finally_body: Optional[Block] = None
+    else_body: Optional[Block]
+    finally_body: Optional[Block]
 
     def __init__(self, body: Block, vars: List['Optional[NameExpr]'],
                  types: List[Optional[Expression]],
@@ -1256,14 +1331,17 @@ def accept(self, visitor: StatementVisitor[T]) -> T:
 
 
 class WithStmt(Statement):
+    __slots__ = ('expr', 'target', 'unanalyzed_type',
+                 'analyzed_types', 'body', 'is_async')
+
     expr: List[Expression]
     target: List[Optional[Lvalue]]
     # Type given by type comments for target, can be None
-    unanalyzed_type: Optional["mypy.types.Type"] = None
+    unanalyzed_type: Optional["mypy.types.Type"]
     # Semantically analyzed types from type comment (TypeList type expanded)
     analyzed_types: List["mypy.types.Type"]
     body: Block
-    is_async = False  # True if `async with ...` (PEP 492, Python 3.5)
+    is_async: bool  # True if `async with ...` (PEP 492, Python 3.5)
 
     def __init__(self, expr: List[Expression], target: List[Optional[Lvalue]],
                  body: Block, target_type: 'Optional[mypy.types.Type]' = None) -> None:
@@ -1273,6 +1351,7 @@ def __init__(self, expr: List[Expression], target: List[Optional[Lvalue]],
         self.unanalyzed_type = target_type
         self.analyzed_types = []
         self.body = body
+        self.is_async = False
 
     def accept(self, visitor: StatementVisitor[T]) -> T:
         return visitor.visit_with_stmt(self)
@@ -1281,10 +1360,12 @@ def accept(self, visitor: StatementVisitor[T]) -> T:
 class PrintStmt(Statement):
     """Python 2 print statement"""
 
+    __slots__ = ('args', 'newline', 'target')
+
     args: List[Expression]
-    newline = False
+    newline: bool
     # The file-like target object (given using >>).
-    target: Optional[Expression] = None
+    target: Optional[Expression]
 
     def __init__(self,
                  args: List[Expression],
@@ -1302,9 +1383,11 @@ def accept(self, visitor: StatementVisitor[T]) -> T:
 class ExecStmt(Statement):
     """Python 2 exec statement"""
 
+    __slots__ = ('expr', 'globals', 'locals')
+
     expr: Expression
-    globals: Optional[Expression] = None
-    locals: Optional[Expression] = None
+    globals: Optional[Expression]
+    locals: Optional[Expression]
 
     def __init__(self, expr: Expression,
                  globals: Optional[Expression],
@@ -1324,7 +1407,9 @@ def accept(self, visitor: StatementVisitor[T]) -> T:
 class IntExpr(Expression):
     """Integer literal"""
 
-    value = 0
+    __slots__ = ('value',)
+
+    value: int  # 0 by default
 
     def __init__(self, value: int) -> None:
         super().__init__()
@@ -1348,7 +1433,9 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class StrExpr(Expression):
     """String literal"""
 
-    value = ''
+    __slots__ = ('value', 'from_python_3')
+
+    value: str  # '' by default
 
     # Keeps track of whether this string originated from Python 2 source code vs
     # Python 3 source code. We need to keep track of this information so we can
@@ -1362,7 +1449,7 @@ class StrExpr(Expression):
     # is meant to be `Literal[u'foo']` or `Literal[b'foo']`.
     #
     # This field keeps track of that information.
-    from_python_3 = True
+    from_python_3: bool
 
     def __init__(self, value: str, from_python_3: bool = False) -> None:
         super().__init__()
@@ -1376,6 +1463,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class BytesExpr(Expression):
     """Bytes literal"""
 
+    __slots__ = ('value',)
+
     # Note: we deliberately do NOT use bytes here because it ends up
     # unnecessarily complicating a lot of the result logic. For example,
     # we'd have to worry about converting the bytes into a format we can
@@ -1385,7 +1474,7 @@ class BytesExpr(Expression):
     #
     # It's more convenient to just store the human-readable representation
     # from the very start.
-    value = ''
+    value: str
 
     def __init__(self, value: str) -> None:
         super().__init__()
@@ -1398,7 +1487,9 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class UnicodeExpr(Expression):
     """Unicode literal (Python 2.x)"""
 
-    value = ''
+    __slots__ = ('value',)
+
+    value: str
 
     def __init__(self, value: str) -> None:
         super().__init__()
@@ -1411,7 +1502,9 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class FloatExpr(Expression):
     """Float literal"""
 
-    value = 0.0
+    __slots__ = ('value',)
+
+    value: float  # 0.0 by default
 
     def __init__(self, value: float) -> None:
         super().__init__()
@@ -1424,6 +1517,10 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class ComplexExpr(Expression):
     """Complex literal"""
 
+    __slots__ = ('value',)
+
+    value: complex
+
     def __init__(self, value: complex) -> None:
         super().__init__()
         self.value = value
@@ -1435,6 +1532,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class EllipsisExpr(Expression):
     """Ellipsis (...)"""
 
+    __slots__ = ()
+
     def accept(self, visitor: ExpressionVisitor[T]) -> T:
         return visitor.visit_ellipsis(self)
 
@@ -1442,7 +1541,10 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class StarExpr(Expression):
     """Star expression"""
 
+    __slots__ = ('expr', 'valid')
+
     expr: Expression
+    valid: bool
 
     def __init__(self, expr: Expression) -> None:
         super().__init__()
@@ -1601,6 +1703,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 
 
 class YieldFromExpr(Expression):
+    __slots__ = ('expr',)
+
     expr: Expression
 
     def __init__(self, expr: Expression) -> None:
@@ -1612,7 +1716,9 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 
 
 class YieldExpr(Expression):
-    expr: Optional[Expression] = None
+    __slots__ = ('expr',)
+
+    expr: Optional[Expression]
 
     def __init__(self, expr: Optional[Expression]) -> None:
         super().__init__()
@@ -1628,10 +1734,12 @@ class IndexExpr(Expression):
     Also wraps type application such as List[int] as a special form.
     """
 
+    __slots__ = ('base', 'index', 'method_type', 'analyzed')
+
     base: Expression
     index: Expression
     # Inferred __getitem__ method type
-    method_type: Optional["mypy.types.Type"] = None
+    method_type: Optional["mypy.types.Type"]
     # If not None, this is actually semantically a type application
     # Class[type, ...] or a type alias initializer.
     analyzed: Union["TypeApplication", "TypeAliasExpr", None]
@@ -1640,6 +1748,7 @@ def __init__(self, base: Expression, index: Expression) -> None:
         super().__init__()
         self.base = base
         self.index = index
+        self.method_type = None
         self.analyzed = None
 
     def accept(self, visitor: ExpressionVisitor[T]) -> T:
@@ -1649,15 +1758,18 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class UnaryExpr(Expression):
     """Unary operation"""
 
-    op = ''
+    __slots__ = ('op', 'expr', 'method_type')
+
+    op: str  # TODO: Enum?
     expr: Expression
     # Inferred operator method type
-    method_type: Optional["mypy.types.Type"] = None
+    method_type: Optional["mypy.types.Type"]
 
     def __init__(self, op: str, expr: Expression) -> None:
         super().__init__()
         self.op = op
         self.expr = expr
+        self.method_type = None
 
     def accept(self, visitor: ExpressionVisitor[T]) -> T:
         return visitor.visit_unary_expr(self)
@@ -1665,6 +1777,9 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 
 class AssignmentExpr(Expression):
     """Assignment expressions in Python 3.8+, like "a := 2"."""
+
+    __slots__ = ('target', 'value')
+
     def __init__(self, target: Expression, value: Expression) -> None:
         super().__init__()
         self.target = target
@@ -1678,21 +1793,27 @@ class OpExpr(Expression):
     """Binary operation (other than . or [] or comparison operators,
     which have specific nodes)."""
 
-    op = ''
+    __slots__ = ('op', 'left', 'right',
+                 'method_type', 'right_always', 'right_unreachable')
+
+    op: str  # TODO: Enum?
     left: Expression
     right: Expression
     # Inferred type for the operator method type (when relevant).
-    method_type: Optional["mypy.types.Type"] = None
+    method_type: Optional["mypy.types.Type"]
     # Per static analysis only: Is the right side going to be evaluated every time?
-    right_always = False
+    right_always: bool
     # Per static analysis only: Is the right side unreachable?
-    right_unreachable = False
+    right_unreachable: bool
 
     def __init__(self, op: str, left: Expression, right: Expression) -> None:
         super().__init__()
         self.op = op
         self.left = left
         self.right = right
+        self.method_type = None
+        self.right_always = False
+        self.right_unreachable = False
 
     def accept(self, visitor: ExpressionVisitor[T]) -> T:
         return visitor.visit_op_expr(self)
@@ -1701,6 +1822,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class ComparisonExpr(Expression):
     """Comparison expression (e.g. a < b > c < d)."""
 
+    __slots__ = ('operators', 'operands', 'method_types')
+
     operators: List[str]
     operands: List[Expression]
     # Inferred type for the operator methods (when relevant; None for 'is').
@@ -1729,9 +1852,11 @@ class SliceExpr(Expression):
     This is only valid as index in index expressions.
     """
 
-    begin_index: Optional[Expression] = None
-    end_index: Optional[Expression] = None
-    stride: Optional[Expression] = None
+    __slots__ = ('begin_index', 'end_index', 'stride')
+
+    begin_index: Optional[Expression]
+    end_index: Optional[Expression]
+    stride: Optional[Expression]
 
     def __init__(self, begin_index: Optional[Expression],
                  end_index: Optional[Expression],
@@ -1748,6 +1873,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class CastExpr(Expression):
     """Cast expression cast(type, expr)."""
 
+    __slots__ = ('expr', 'type')
+
     expr: Expression
     type: "mypy.types.Type"
 
@@ -1763,9 +1890,11 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class RevealExpr(Expression):
     """Reveal type expression reveal_type(expr) or reveal_locals() expression."""
 
-    expr: Optional[Expression] = None
-    kind: int = 0
-    local_nodes: Optional[List[Var]] = None
+    __slots__ = ('expr', 'kind', 'local_nodes')
+
+    expr: Optional[Expression]
+    kind: int
+    local_nodes: Optional[List[Var]]
 
     def __init__(
             self, kind: int,
@@ -1783,14 +1912,17 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class SuperExpr(Expression):
     """Expression super().name"""
 
-    name = ''
-    info: Optional["TypeInfo"] = None  # Type that contains this super expression
+    __slots__ = ('name', 'info', 'call')
+
+    name: str
+    info: Optional["TypeInfo"]  # Type that contains this super expression
     call: CallExpr  # The expression super(...)
 
     def __init__(self, name: str, call: CallExpr) -> None:
         super().__init__()
         self.name = name
         self.call = call
+        self.info = None
 
     def accept(self, visitor: ExpressionVisitor[T]) -> T:
         return visitor.visit_super_expr(self)
@@ -1820,6 +1952,8 @@ def is_dynamic(self) -> bool:
 class ListExpr(Expression):
     """List literal expression [...]."""
 
+    __slots__ = ('items',)
+
     items: List[Expression]
 
     def __init__(self, items: List[Expression]) -> None:
@@ -1833,6 +1967,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class DictExpr(Expression):
     """Dictionary literal expression {key: value, ...}."""
 
+    __slots__ = ('items',)
+
     items: List[Tuple[Optional[Expression], Expression]]
 
     def __init__(self, items: List[Tuple[Optional[Expression], Expression]]) -> None:
@@ -1848,6 +1984,8 @@ class TupleExpr(Expression):
 
     Also lvalue sequences (..., ...) and [..., ...]"""
 
+    __slots__ = ('items',)
+
     items: List[Expression]
 
     def __init__(self, items: List[Expression]) -> None:
@@ -1861,6 +1999,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class SetExpr(Expression):
     """Set literal expression {value, ...}."""
 
+    __slots__ = ('items',)
+
     items: List[Expression]
 
     def __init__(self, items: List[Expression]) -> None:
@@ -1874,6 +2014,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class GeneratorExpr(Expression):
     """Generator expression ... for ... in ... [ for ...  in ... ] [ if ... ]."""
 
+    __slots__ = ('left_expr', 'sequences', 'condlists', 'is_async', 'indices')
+
     left_expr: Expression
     sequences: List[Expression]
     condlists: List[List[Expression]]
@@ -1897,6 +2039,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class ListComprehension(Expression):
     """List comprehension (e.g. [x + 1 for x in a])"""
 
+    __slots__ = ('generator',)
+
     generator: GeneratorExpr
 
     def __init__(self, generator: GeneratorExpr) -> None:
@@ -1910,6 +2054,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class SetComprehension(Expression):
     """Set comprehension (e.g. {x + 1 for x in a})"""
 
+    __slots__ = ('generator',)
+
     generator: GeneratorExpr
 
     def __init__(self, generator: GeneratorExpr) -> None:
@@ -1923,6 +2069,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class DictionaryComprehension(Expression):
     """Dictionary comprehension (e.g. {k: v for k, v in a}"""
 
+    __slots__ = ('key', 'value', 'sequences', 'condlists', 'is_async', 'indices')
+
     key: Expression
     value: Expression
     sequences: List[Expression]
@@ -1948,6 +2096,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class ConditionalExpr(Expression):
     """Conditional expression (e.g. x if y else z)"""
 
+    __slots__ = ('cond', 'if_expr', 'else_expr')
+
     cond: Expression
     if_expr: Expression
     else_expr: Expression
@@ -1965,6 +2115,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class BackquoteExpr(Expression):
     """Python 2 expression `...`."""
 
+    __slots__ = ('expr',)
+
     expr: Expression
 
     def __init__(self, expr: Expression) -> None:
@@ -1978,6 +2130,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class TypeApplication(Expression):
     """Type application expr[type, ...]"""
 
+    __slots__ = ('expr', 'types')
+
     expr: Expression
     types: List["mypy.types.Type"]
 
@@ -2006,8 +2160,11 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 
 class TypeVarLikeExpr(SymbolNode, Expression):
     """Base class for TypeVarExpr and ParamSpecExpr."""
-    _name = ''
-    _fullname = ''
+
+    __slots__ = ('_name', '_fullname', 'upper_bound', 'variance')
+
+    _name: str
+    _fullname: str
     # Upper bound: only subtypes of upper_bound are valid as values. By default
     # this is 'object', meaning no restriction.
     upper_bound: "mypy.types.Type"
@@ -2015,7 +2172,7 @@ class TypeVarLikeExpr(SymbolNode, Expression):
     # TypeVar(..., covariant=True) defines a covariant type variable.
     # TypeVar(..., contravariant=True) defines a contravariant type
     # variable.
-    variance = INVARIANT
+    variance: int
 
     def __init__(
         self, name: str, fullname: str, upper_bound: 'mypy.types.Type', variance: int = INVARIANT
@@ -2046,6 +2203,9 @@ class TypeVarExpr(TypeVarLikeExpr):
      1. a generic class that uses the type variable as a type argument or
      2. a generic function that refers to the type variable in its signature.
     """
+
+    __slots__ = ('values',)
+
     # Value restriction: only types in the list are valid as values. If the
     # list is empty, there is no restriction.
     values: List["mypy.types.Type"]
@@ -2080,6 +2240,8 @@ def deserialize(cls, data: JsonDict) -> 'TypeVarExpr':
 
 
 class ParamSpecExpr(TypeVarLikeExpr):
+    __slots__ = ()
+
     def accept(self, visitor: ExpressionVisitor[T]) -> T:
         return visitor.visit_paramspec_expr(self)
 
@@ -2106,6 +2268,8 @@ def deserialize(cls, data: JsonDict) -> 'ParamSpecExpr':
 class TypeAliasExpr(Expression):
     """Type alias expression (rvalue)."""
 
+    __slots__ = ('type', 'tvars', 'no_args', 'node')
+
     # The target type.
     type: "mypy.types.Type"
     # Names of unbound type variables used to define the alias
@@ -2115,7 +2279,8 @@ class TypeAliasExpr(Expression):
     #     A = List
     # and
     #     A = List[Any]
-    no_args: bool = False
+    no_args: bool
+    node: 'TypeAlias'
 
     def __init__(self, node: 'TypeAlias') -> None:
         super().__init__()
@@ -2131,10 +2296,12 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class NamedTupleExpr(Expression):
     """Named tuple expression namedtuple(...) or NamedTuple(...)."""
 
+    __slots__ = ('info', 'is_typed')
+
     # The class representation of this named tuple (its tuple_type attribute contains
     # the tuple item types)
     info: "TypeInfo"
-    is_typed = False  # whether this class was created with typing.NamedTuple
+    is_typed: bool  # whether this class was created with typing.NamedTuple
 
     def __init__(self, info: 'TypeInfo', is_typed: bool = False) -> None:
         super().__init__()
@@ -2148,6 +2315,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class TypedDictExpr(Expression):
     """Typed dict expression TypedDict(...)."""
 
+    __slots__ = ('info',)
+
     # The class representation of this typed dict
     info: "TypeInfo"
 
@@ -2162,6 +2331,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class EnumCallExpr(Expression):
     """Named tuple expression Enum('name', 'val1 val2 ...')."""
 
+    __slots__ = ('info', 'items', 'values')
+
     # The class representation of this enumerated type
     info: "TypeInfo"
     # The item names (for debugging)
@@ -2182,6 +2353,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class PromoteExpr(Expression):
     """Ducktype class decorator expression _promote(...)."""
 
+    __slots__ = ('type',)
+
     type: "mypy.types.Type"
 
     def __init__(self, type: 'mypy.types.Type') -> None:
@@ -2195,19 +2368,20 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class NewTypeExpr(Expression):
     """NewType expression NewType(...)."""
 
+    __slots__ = ('name', 'old_type', 'info')
+
     name: str
     # The base type (the second argument to NewType)
-    old_type: Optional["mypy.types.Type"] = None
+    old_type: Optional["mypy.types.Type"]
     # The synthesized class representing the new type (inherits old_type)
-    info: Optional["TypeInfo"] = None
+    info: Optional["TypeInfo"]
 
     def __init__(self, name: str, old_type: 'Optional[mypy.types.Type]', line: int,
                  column: int) -> None:
-        super().__init__()
+        super().__init__(line=line, column=column)
         self.name = name
         self.old_type = old_type
-        self.line = line
-        self.column = column
+        self.info = None
 
     def accept(self, visitor: ExpressionVisitor[T]) -> T:
         return visitor.visit_newtype_expr(self)
@@ -2216,6 +2390,8 @@ def accept(self, visitor: ExpressionVisitor[T]) -> T:
 class AwaitExpr(Expression):
     """Await expression (await ...)."""
 
+    __slots__ = ('expr',)
+
     expr: Expression
 
     def __init__(self, expr: Expression) -> None:
@@ -2237,10 +2413,12 @@ class TempNode(Expression):
     some fixed type.
     """
 
+    __slots__ = ('type', 'no_rhs')
+
     type: "mypy.types.Type"
     # Is this TempNode used to indicate absence of a right hand side in an annotated assignment?
     # (e.g. for 'x: int' the rvalue is TempNode(AnyType(TypeOfAny.special_form), no_rhs=True))
-    no_rhs: bool = False
+    no_rhs: bool
 
     def __init__(self,
                  typ: 'mypy.types.Type',
@@ -2275,7 +2453,17 @@ class is generic then it will be a type constructor of higher kind.
     the appropriate number of arguments.
     """
 
-    _fullname: Bogus[str] = None  # type: ignore  # Fully qualified name
+    __slots__ = (
+        '_fullname', 'module_name', 'defn', 'mro', '_mro_refs', 'bad_mro', 'is_final',
+        'declared_metaclass', 'metaclass_type', 'names', 'is_abstract',
+        'is_protocol', 'runtime_protocol', 'abstract_attributes',
+        'deletable_attributes', 'slots', 'assuming', 'assuming_proper',
+        'inferring', 'is_enum', 'fallback_to_any', 'type_vars', 'bases',
+        '_promote', 'tuple_type', 'is_named_tuple', 'typeddict_type',
+        'is_newtype', 'is_intersection', 'metadata',
+    )
+
+    _fullname: 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.
@@ -2286,16 +2474,17 @@ class is generic then it will be a type constructor of higher kind.
     mro: List["TypeInfo"]
     # Used to stash the names of the mro classes temporarily between
     # deserialization and fixup. See deserialize() for why.
-    _mro_refs: Optional[List[str]] = None
-    bad_mro = False  # Could not construct full MRO
+    _mro_refs: Optional[List[str]]
+    bad_mro: bool  # Could not construct full MRO
+    is_final: bool
 
-    declared_metaclass: Optional["mypy.types.Instance"] = None
-    metaclass_type: Optional["mypy.types.Instance"] = None
+    declared_metaclass: Optional["mypy.types.Instance"]
+    metaclass_type: Optional["mypy.types.Instance"]
 
     names: "SymbolTable"  # Names defined directly in this type
-    is_abstract = False                    # Does the class have any abstract attributes?
-    is_protocol = False                    # Is this a protocol class?
-    runtime_protocol = False               # Does this protocol support isinstance checks?
+    is_abstract: bool                      # Does the class have any abstract attributes?
+    is_protocol: bool                      # Is this a protocol class?
+    runtime_protocol: bool                 # Does this protocol support isinstance checks?
     abstract_attributes: List[str]
     deletable_attributes: List[str]  # Used by mypyc only
     # Does this type have concrete `__slots__` defined?
@@ -2340,13 +2529,13 @@ class is generic then it will be a type constructor of higher kind.
 
     # Classes inheriting from Enum shadow their true members with a __getattr__, so we
     # have to treat them as a special case.
-    is_enum = False
+    is_enum: bool
     # If true, any unknown attributes should have type 'Any' instead
     # of generating a type error.  This would be true if there is a
     # base class with type 'Any', but other use cases may be
     # possible. This is similar to having __getattr__ that returns Any
     # (and __setattr__), but without the __getattr__ method.
-    fallback_to_any = False
+    fallback_to_any: bool
 
     # Information related to type annotations.
 
@@ -2360,27 +2549,27 @@ class is generic then it will be a type constructor of higher kind.
     # even though it's not a subclass in Python.  The non-standard
     # `@_promote` decorator introduces this, and there are also
     # several builtin examples, in particular `int` -> `float`.
-    _promote: Optional["mypy.types.Type"] = None
+    _promote: Optional["mypy.types.Type"]
 
     # Representation of a Tuple[...] base class, if the class has any
     # (e.g., for named tuples). If this is not None, the actual Type
     # object used for this class is not an Instance but a TupleType;
     # the corresponding Instance is set as the fallback type of the
     # tuple type.
-    tuple_type: Optional["mypy.types.TupleType"] = None
+    tuple_type: Optional["mypy.types.TupleType"]
 
     # Is this a named tuple type?
-    is_named_tuple = False
+    is_named_tuple: bool
 
     # If this class is defined by the TypedDict type constructor,
     # then this is not None.
-    typeddict_type: Optional["mypy.types.TypedDictType"] = None
+    typeddict_type: Optional["mypy.types.TypedDictType"]
 
     # Is this a newtype type?
-    is_newtype = False
+    is_newtype: bool
 
     # Is this a synthesized intersection type?
-    is_intersection = False
+    is_intersection: bool
 
     # This is a dictionary that will be serialized and un-serialized as is.
     # It is useful for plugins to add their data to save in the cache.
@@ -2395,13 +2584,17 @@ class is generic then it will be a type constructor of higher kind.
     def __init__(self, names: 'SymbolTable', defn: ClassDef, module_name: str) -> None:
         """Initialize a TypeInfo."""
         super().__init__()
+        self._fullname = defn.fullname
         self.names = names
         self.defn = defn
         self.module_name = module_name
         self.type_vars = []
         self.bases = []
         self.mro = []
-        self._fullname = defn.fullname
+        self._mro_refs = None
+        self.bad_mro = False
+        self.declared_metaclass = None
+        self.metaclass_type = None
         self.is_abstract = False
         self.abstract_attributes = []
         self.deletable_attributes = []
@@ -2409,9 +2602,19 @@ def __init__(self, names: 'SymbolTable', defn: ClassDef, module_name: str) -> No
         self.assuming = []
         self.assuming_proper = []
         self.inferring = []
+        self.is_protocol = False
+        self.runtime_protocol = False
         self.add_type_vars()
-        self.metadata = {}
         self.is_final = False
+        self.is_enum = False
+        self.fallback_to_any = False
+        self._promote = None
+        self.tuple_type = None
+        self.is_named_tuple = False
+        self.typeddict_type = None
+        self.is_newtype = False
+        self.is_intersection = False
+        self.metadata = {}
 
     def add_type_vars(self) -> None:
         if self.defn.type_vars:
@@ -2631,6 +2834,9 @@ def deserialize(cls, data: JsonDict) -> 'TypeInfo':
 
 
 class FakeInfo(TypeInfo):
+
+    __slots__ = ('msg',)
+
     # types.py defines a single instance of this class, called types.NOT_READY.
     # This instance is used as a temporary placeholder in the process of de-serialization
     # of 'Instance' types. The de-serialization happens in two steps: In the first step,
@@ -2864,6 +3070,8 @@ class C(Sequence[C]): ...
     something that can support general recursive types.
     """
 
+    __slots__ = ('_fullname', 'node', 'line', 'becomes_typeinfo')
+
     def __init__(self, fullname: str, node: Node, line: int, *,
                  becomes_typeinfo: bool = False) -> None:
         self._fullname = fullname
@@ -3075,6 +3283,8 @@ class SymbolTable(Dict[str, SymbolTableNode]):
     This is used for module, class and function namespaces.
     """
 
+    __slots__ = ()
+
     def __str__(self) -> str:
         a: List[str] = []
         for key, value in self.items():
diff --git a/mypy/types.py b/mypy/types.py
--- a/mypy/types.py
+++ b/mypy/types.py
@@ -89,6 +89,9 @@ class TypeOfAny:
     """
     This class describes different types of Any. Each 'Any' can be of only one type at a time.
     """
+
+    __slots__ = ()
+
     # Was this Any type inferred without a type annotation?
     unannotated: Final = 1
     # Does this Any come from an explicit type annotation?
@@ -278,6 +281,9 @@ def copy_modified(self, *,
 
 class TypeGuardedType(Type):
     """Only used by find_instance_check() etc."""
+
+    __slots__ = ('type_guard',)
+
     def __init__(self, type_guard: Type):
         super().__init__(line=type_guard.line, column=type_guard.column)
         self.type_guard = type_guard
@@ -292,6 +298,8 @@ class ProperType(Type):
     Every type except TypeAliasType must inherit from this type.
     """
 
+    __slots__ = ()
+
 
 class TypeVarId:
     # A type variable is uniquely identified by its raw id and meta level.
@@ -345,8 +353,11 @@ def is_meta_var(self) -> bool:
 
 
 class TypeVarLikeType(ProperType):
-    name = ''  # Name (may be qualified)
-    fullname = ''  # Fully qualified name
+
+    __slots__ = ('name', 'fullname', 'id')
+
+    name: str  # Name (may be qualified)
+    fullname: str  # Fully qualified name
     id: TypeVarId
 
     def __init__(
@@ -370,9 +381,11 @@ def deserialize(cls, data: JsonDict) -> 'TypeVarLikeType':
 class TypeVarType(TypeVarLikeType):
     """Definition of a single type variable."""
 
+    __slots__ = ('values', 'upper_bound', 'variance')
+
     values: List[Type]  # Value restriction, empty list if no restriction
     upper_bound: Type
-    variance: int = INVARIANT
+    variance: int
 
     def __init__(self, name: str, fullname: str, id: Union[TypeVarId, int], values: List[Type],
                  upper_bound: Type, variance: int = INVARIANT, line: int = -1,
@@ -427,6 +440,8 @@ def deserialize(cls, data: JsonDict) -> 'TypeVarType':
 class ParamSpecType(TypeVarLikeType):
     """Definition of a single ParamSpec variable."""
 
+    __slots__ = ()
+
     def __repr__(self) -> str:
         return self.name
 
@@ -544,9 +559,11 @@ class CallableArgument(ProperType):
     Note that this is a synthetic type for helping parse ASTs, not a real type.
     """
 
+    __slots__ = ('typ', 'name', 'constructor')
+
     typ: Type
-    name: Optional[str] = None
-    constructor: Optional[str] = None
+    name: Optional[str]
+    constructor: Optional[str]
 
     def __init__(self, typ: Type, name: Optional[str], constructor: Optional[str],
                  line: int = -1, column: int = -1) -> None:
@@ -572,6 +589,8 @@ class TypeList(ProperType):
     types before they are processed into Callable types.
     """
 
+    __slots__ = ('items',)
+
     items: List[Type]
 
     def __init__(self, items: List[Type], line: int = -1, column: int = -1) -> None:
@@ -672,15 +691,18 @@ class UninhabitedType(ProperType):
         is_subtype(UninhabitedType, T) = True
     """
 
-    is_noreturn = False  # Does this come from a NoReturn?  Purely for error messages.
+    __slots__ = ('ambiguous', 'is_noreturn',)
+
+    is_noreturn: bool  # Does this come from a NoReturn?  Purely for error messages.
     # It is important to track whether this is an actual NoReturn type, or just a result
     # of ambiguous type inference, in the latter case we don't want to mark a branch as
     # unreachable in binder.
-    ambiguous = False  # Is this a result of inference for a variable without constraints?
+    ambiguous: bool  # Is this a result of inference for a variable without constraints?
 
     def __init__(self, is_noreturn: bool = False, line: int = -1, column: int = -1) -> None:
         super().__init__(line, column)
         self.is_noreturn = is_noreturn
+        self.ambiguous = False
 
     def can_be_true_default(self) -> bool:
         return False
@@ -751,6 +773,8 @@ class ErasedType(ProperType):
     it is ignored during type inference.
     """
 
+    __slots__ = ()
+
     def accept(self, visitor: 'TypeVisitor[T]') -> T:
         return visitor.visit_erased_type(self)
 
@@ -761,7 +785,9 @@ class DeletedType(ProperType):
     These can be used as lvalues but not rvalues.
     """
 
-    source: Optional[str] = ""  # May be None; name that generated this value
+    __slots__ = ('source',)
+
+    source: Optional[str]  # May be None; name that generated this value
 
     def __init__(self, source: Optional[str] = None, line: int = -1, column: int = -1) -> None:
         super().__init__(line, column)
@@ -1277,6 +1303,8 @@ class Overloaded(FunctionLike):
     implementation.
     """
 
+    __slots__ = ('_items', 'fallback')
+
     _items: List[CallableType]  # Must not be empty
 
     def __init__(self, items: List[CallableType]) -> None:
@@ -1345,9 +1373,12 @@ class TupleType(ProperType):
         implicit: If True, derived from a tuple expression (t,....) instead of Tuple[t, ...]
     """
 
+    __slots__ = ('items', 'partial_fallback', 'implicit',
+                 'can_be_true', 'can_be_false')
+
     items: List[Type]
     partial_fallback: Instance
-    implicit = False
+    implicit: bool
 
     def __init__(self, items: List[Type], fallback: Instance, line: int = -1,
                  column: int = -1, implicit: bool = False) -> None:
@@ -1420,6 +1451,9 @@ class TypedDictType(ProperType):
     TODO: The fallback structure is perhaps overly complicated.
     """
 
+    __slots__ = ('items', 'required_keys', 'fallback',
+                 'can_be_true', 'can_be_false')
+
     items: "OrderedDict[str, Type]"  # item_name -> item_type
     required_keys: Set[str]
     fallback: Instance
@@ -1557,6 +1591,9 @@ class RawExpressionType(ProperType):
             ],
         )
     """
+
+    __slots__ = ('literal_value', 'base_type_name', 'note')
+
     def __init__(self,
                  literal_value: Optional[LiteralValue],
                  base_type_name: str,
@@ -1684,6 +1721,8 @@ class StarType(ProperType):
     This is not a real type but a syntactic AST construct.
     """
 
+    __slots__ = ('type',)
+
     type: Type
 
     def __init__(self, type: Type, line: int = -1, column: int = -1) -> None:
@@ -1789,12 +1828,14 @@ class PartialType(ProperType):
           x = 1  # Infer actual type int for x
     """
 
+    __slots__ = ('type', 'var', 'value_type')
+
     # None for the 'None' partial type; otherwise a generic class
-    type: Optional[mypy.nodes.TypeInfo] = None
+    type: Optional[mypy.nodes.TypeInfo]
     var: mypy.nodes.Var
     # For partial defaultdict[K, V], the type V (K is unknown). If V is generic,
     # the type argument is Any and will be replaced later.
-    value_type: Optional[Instance] = None
+    value_type: Optional[Instance]
 
     def __init__(self,
                  type: 'Optional[mypy.nodes.TypeInfo]',
@@ -1817,6 +1858,8 @@ class EllipsisType(ProperType):
     A semantically analyzed type will never have ellipsis types.
     """
 
+    __slots__ = ()
+
     def accept(self, visitor: 'TypeVisitor[T]') -> T:
         assert isinstance(visitor, SyntheticTypeVisitor)
         return visitor.visit_ellipsis_type(self)
@@ -1853,6 +1896,8 @@ class TypeType(ProperType):
     assumption).
     """
 
+    __slots__ = ('item',)
+
     # This can't be everything, but it can be a class reference,
     # a generic class instance, a union, Any, a type variable...
     item: ProperType
@@ -1912,6 +1957,8 @@ class str(Sequence[str]): ...
     exist.
     """
 
+    __slots__ = ('fullname', 'args')
+
     def __init__(self, fullname: Optional[str], args: List[Type], line: int) -> None:
         super().__init__(line)
         self.fullname = fullname  # Must be a valid full name of an actual node (or None).


Test patch: