Skip to content

Incremental crash with double re-exported alias used in function annotation #13825

Closed
@ilevkivskyi

Description

@ilevkivskyi

Here is a (relatively) minimal repro:

[case testOidCrash]
import m

[file m.py]
import f
[file m.py.3]
import f
# modify

[file f.py]
import c
def foo(arg: c.Oid) -> None: pass

[file c.py]
from types import Oid

[file types.py]
import pb1
Oid = pb1.Oid
[file types.py.2]
import pb1, pb2
Oid = pb2.Oid

[file pb1.py]
class Oid: ...
[file pb2.py.2]
class Oid: ...
[file pb1.py.2]

[out]
[out2]
[out3]

This crashes with

/home/ivan/src/mypy/mypy/test/testcheck.py:81: in run_case
    self.run_case_once(testcase, ops, step)
/home/ivan/src/mypy/mypy/test/testcheck.py:147: in run_case_once
    res = build.build(sources=sources, options=options, alt_lib_path=test_temp_dir)
/home/ivan/src/mypy/mypy/build.py:193: in build
    result = _build(
/home/ivan/src/mypy/mypy/build.py:276: in _build
    graph = dispatch(sources, manager, stdout)
/home/ivan/src/mypy/mypy/build.py:2891: in dispatch
    process_graph(graph, manager)
/home/ivan/src/mypy/mypy/build.py:3268: in process_graph
    process_fresh_modules(graph, prev_scc, manager)
/home/ivan/src/mypy/mypy/build.py:3349: in process_fresh_modules
    graph[id].fix_cross_refs()
/home/ivan/src/mypy/mypy/build.py:2112: in fix_cross_refs
    fixup_module(self.tree, self.manager.modules, self.options.use_fine_grained_cache)
/home/ivan/src/mypy/mypy/fixup.py:53: in fixup_module
    node_fixer.visit_symbol_table(tree.names, tree.fullname)
/home/ivan/src/mypy/mypy/fixup.py:127: in visit_symbol_table
    value.node.accept(self)
/home/ivan/src/mypy/mypy/nodes.py:822: in accept
    return visitor.visit_func_def(self)
/home/ivan/src/mypy/mypy/fixup.py:135: in visit_func_def
    func.type.accept(self.type_fixer)
/home/ivan/src/mypy/mypy/types.py:1792: in accept
    return visitor.visit_callable_type(self)
/home/ivan/src/mypy/mypy/fixup.py:229: in visit_callable_type
    argt.accept(self)
/home/ivan/src/mypy/mypy/types.py:1283: in accept
    return visitor.visit_instance(self)
/home/ivan/src/mypy/mypy/fixup.py:196: in visit_instance
    inst.type = lookup_fully_qualified_typeinfo(
/home/ivan/src/mypy/mypy/fixup.py:331: in lookup_fully_qualified_typeinfo
    stnode = lookup_fully_qualified(name, modules, raise_on_missing=not allow_missing)
/home/ivan/src/mypy/mypy/lookup.py:49: in lookup_fully_qualified
    assert key in names, f"Cannot find component {key!r} for {name!r}"
AssertionError: Cannot find component 'Oid' for 'pb1.Oid'

The problem is that TypeIndirectionVisitor uses type_map for a given module to find indirect dependencies. This is however problematic in various cases, for example types used in a function definition may never appear as a type of some expression (type map of f.py in this case is just empty). I am not sure what is the best solution (for example fine-grained mode doesn't have this problem as it uses a proper node visitor). Maybe we can just add all types encountered in symbol tables?

cc @JukkaL @Michael0x2a

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions