# Buggy code
def add_class_tvars(
    t: ProperType,
    isuper: Optional[Instance],
    is_classmethod: bool,
    original_type: Type,
    original_vars: Optional[List[TypeVarDef]] = None,
) -> Type:
    """Instantiate type variables during analyze_class_attribute_access,
    e.g T and Q in the following:

    class A(Generic[T]):
        @classmethod
        def foo(cls: Type[Q]) -> Tuple[T, Q]: ...

    class B(A[str]): pass
    B.foo()

    Args:
        t: Declared type of the method (or property)
        isuper: Current instance mapped to the superclass where method was defined, this
            is usually done by map_instance_to_supertype()
        is_classmethod: True if this method is decorated with @classmethod
        original_type: The value of the type B in the expression B.foo() or the corresponding
            component in case of a union (this is used to bind the self-types)
        original_vars: Type variables of the class callable on which the method was accessed
    Returns:
        Expanded method type with added type variables (when needed).
    """
    # TODO: verify consistency between Q and T

    # We add class type variables if the class method is accessed on class object
    # without applied type arguments, this matches the behavior of __init__().
    # For example (continuing the example in docstring):
    #     A       # The type of callable is def [T] () -> A[T], _not_ def () -> A[Any]
    #     A[int]  # The type of callable is def () -> A[int]
    # and
    #     A.foo       # The type is generic def [T] () -> Tuple[T, A[T]]
    #     A[int].foo  # The type is non-generic def () -> Tuple[int, A[int]]
    #
    # This behaviour is useful for defining alternative constructors for generic classes.
    # To achieve such behaviour, we add the class type variables that are still free
    # (i.e. appear in the return type of the class object on which the method was accessed).
    if isinstance(t, CallableType):
        tvars = original_vars if original_vars is not None else []
        if is_classmethod:
            t = freshen_function_type_vars(t)
            t = bind_self(t, original_type, is_classmethod=True)
            assert isuper is not None
            t = cast(CallableType, expand_type_by_instance(t, isuper))
        return t.copy_modified(variables=tvars + t.variables)
    elif isinstance(t, Overloaded):
        return Overloaded(
            [
                cast(
                    CallableType,
                    add_class_tvars(
                        item,
                        isuper,
                        is_classmethod,
                        original_type,
                        original_vars=original_vars,
                    ),
                )
                for item in t.items()
            ]
        )
    if isuper is not None:
        t = cast(ProperType, expand_type_by_instance(t, isuper))
    return t


# Traceback (AssertionError)
Traceback (most recent call last):
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/Users/jukka/src/mypy/mypy/__main__.py", line 12, in <module>
main(None, sys.stdout, sys.stderr)
File "/Users/jukka/src/mypy/mypy/main.py", line 89, in main
res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr)
File "/Users/jukka/src/mypy/mypy/build.py", line 167, in build
sources, options, alt_lib_path, flush_errors, fscache, stdout, stderr, extra_plugins
File "/Users/jukka/src/mypy/mypy/build.py", line 235, in _build
graph = dispatch(sources, manager, stdout)
File "/Users/jukka/src/mypy/mypy/build.py", line 2620, in dispatch
process_graph(graph, manager)
File "/Users/jukka/src/mypy/mypy/build.py", line 2929, in process_graph
process_stale_scc(graph, scc, manager)
File "/Users/jukka/src/mypy/mypy/build.py", line 3047, in process_stale_scc
graph[id].write_cache()
File "/Users/jukka/src/mypy/mypy/build.py", line 2244, in write_cache
self.manager)
File "/Users/jukka/src/mypy/mypy/build.py", line 1410, in write_cache
data = tree.serialize()
File "/Users/jukka/src/mypy/mypy/nodes.py", line 302, in serialize
'names': self.names.serialize(self._fullname),
File "/Users/jukka/src/mypy/mypy/nodes.py", line 3083, in serialize
data[key] = value.serialize(fullname, key)
File "/Users/jukka/src/mypy/mypy/nodes.py", line 3021, in serialize
data['node'] = self.node.serialize()
File "/Users/jukka/src/mypy/mypy/nodes.py", line 882, in serialize
'type': None if self.type is None else self.type.serialize(),
File "/Users/jukka/src/mypy/mypy/types.py", line 1218, in serialize
'arg_types': [t.serialize() for t in self.arg_types],
File "/Users/jukka/src/mypy/mypy/types.py", line 1218, in <listcomp>
'arg_types': [t.serialize() for t in self.arg_types],
File "/Users/jukka/src/mypy/mypy/types.py", line 885, in serialize
assert not self.id.is_meta_var()
AssertionError

# Fixed code
def add_class_tvars(
    t: ProperType,
    isuper: Optional[Instance],
    is_classmethod: bool,
    original_type: Type,
    original_vars: Optional[List[TypeVarDef]] = None,
) -> Type:
    """Instantiate type variables during analyze_class_attribute_access,
    e.g T and Q in the following:

    class A(Generic[T]):
        @classmethod
        def foo(cls: Type[Q]) -> Tuple[T, Q]: ...

    class B(A[str]): pass
    B.foo()

    Args:
        t: Declared type of the method (or property)
        isuper: Current instance mapped to the superclass where method was defined, this
            is usually done by map_instance_to_supertype()
        is_classmethod: True if this method is decorated with @classmethod
        original_type: The value of the type B in the expression B.foo() or the corresponding
            component in case of a union (this is used to bind the self-types)
        original_vars: Type variables of the class callable on which the method was accessed
    Returns:
        Expanded method type with added type variables (when needed).
    """
    # TODO: verify consistency between Q and T

    # We add class type variables if the class method is accessed on class object
    # without applied type arguments, this matches the behavior of __init__().
    # For example (continuing the example in docstring):
    #     A       # The type of callable is def [T] () -> A[T], _not_ def () -> A[Any]
    #     A[int]  # The type of callable is def () -> A[int]
    # and
    #     A.foo       # The type is generic def [T] () -> Tuple[T, A[T]]
    #     A[int].foo  # The type is non-generic def () -> Tuple[int, A[int]]
    #
    # This behaviour is useful for defining alternative constructors for generic classes.
    # To achieve such behaviour, we add the class type variables that are still free
    # (i.e. appear in the return type of the class object on which the method was accessed).
    if isinstance(t, CallableType):
        tvars = original_vars if original_vars is not None else []
        if is_classmethod:
            t = freshen_function_type_vars(t)
            t = bind_self(t, original_type, is_classmethod=True)
            assert isuper is not None
            t = cast(CallableType, expand_type_by_instance(t, isuper))
            freeze_type_vars(t)
        return t.copy_modified(variables=tvars + t.variables)
    elif isinstance(t, Overloaded):
        return Overloaded(
            [
                cast(
                    CallableType,
                    add_class_tvars(
                        item,
                        isuper,
                        is_classmethod,
                        original_type,
                        original_vars=original_vars,
                    ),
                )
                for item in t.items()
            ]
        )
    if isuper is not None:
        t = cast(ProperType, expand_type_by_instance(t, isuper))
    return t