Skip to content

Wrong types and crash with polymorphic Callable #10244

Closed
@andriusstank

Description

@andriusstank

Crash Report

First of all, the code that makess mypy crash:

from dataclasses import dataclass
from typing import Generic, TypeVar, Callable

T = TypeVar('T')
R = TypeVar('R')
X = TypeVar('X')

@dataclass
class Box(Generic[T]):
    inner: T

@dataclass
class Cont(Generic[R]):
    run: Box[Callable[[X], R]]

def f(c: Cont[R]) -> R:
    return c.run.inner(3)

def const_two(x: T) -> str:
    return "two"

c = Cont(Box(const_two))

Adding type annotation at the last line c: Cont[str] = Cont(Box(const_two)) prevents the crash.

There's another problem - mypy gets types in function f wrong. Here c.run.inner returns type R, while mypy insists it must by int.

17: error: Incompatible return value type (got "int", expected "R")

Traceback

Traceback (most recent call last):
  File "/home/as/miniconda3/envs/debug_mypy/bin/mypy", line 8, in <module>
    sys.exit(console_entry())
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/__main__.py", line 11, in console_entry
    main(None, sys.stdout, sys.stderr)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/main.py", line 98, in main
    res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/build.py", line 179, in build
    result = _build(
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/build.py", line 253, in _build
    graph = dispatch(sources, manager, stdout)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/build.py", line 2688, in dispatch
    process_graph(graph, manager)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/build.py", line 3012, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/build.py", line 3110, in process_stale_scc
    graph[id].type_check_first_pass()
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/build.py", line 2164, in type_check_first_pass
    self.type_checker().check_first_pass()
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checker.py", line 294, in check_first_pass
    self.accept(d)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checker.py", line 401, in accept
    stmt.accept(self)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/nodes.py", line 1073, in accept
    return visitor.visit_assignment_stmt(self)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checker.py", line 2010, in visit_assignment_stmt
    self.check_assignment(s.lvalues[-1], s.rvalue, s.type is None, s.new_syntax)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checker.py", line 2146, in check_assignment
    rvalue_type = self.expr_checker.accept(rvalue)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checkexpr.py", line 3902, in accept
    typ = node.accept(self)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/nodes.py", line 1558, in accept
    return visitor.visit_call_expr(self)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checkexpr.py", line 270, in visit_call_expr
    return self.visit_call_expr_inner(e, allow_none_return=allow_none_return)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checkexpr.py", line 352, in visit_call_expr_inner
    ret_type = self.check_call_expr_with_callee_type(callee_type, e, fullname,
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checkexpr.py", line 857, in check_call_expr_with_callee_type
    return self.check_call(callee_type, e.args, e.arg_kinds, e,
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checkexpr.py", line 916, in check_call
    return self.check_callable_call(callee, args, arg_kinds, context, arg_names,
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checkexpr.py", line 1004, in check_callable_call
    callee = self.infer_function_type_arguments(
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checkexpr.py", line 1207, in infer_function_type_arguments
    arg_types = self.infer_arg_types_in_context(
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checkexpr.py", line 1106, in infer_arg_types_in_context
    res[ai] = self.accept(args[ai], callee.arg_types[i])
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checkexpr.py", line 3902, in accept
    typ = node.accept(self)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/nodes.py", line 1558, in accept
    return visitor.visit_call_expr(self)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checkexpr.py", line 270, in visit_call_expr
    return self.visit_call_expr_inner(e, allow_none_return=allow_none_return)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checkexpr.py", line 352, in visit_call_expr_inner
    ret_type = self.check_call_expr_with_callee_type(callee_type, e, fullname,
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checkexpr.py", line 857, in check_call_expr_with_callee_type
    return self.check_call(callee_type, e.args, e.arg_kinds, e,
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checkexpr.py", line 916, in check_call
    return self.check_callable_call(callee, args, arg_kinds, context, arg_names,
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checkexpr.py", line 1002, in check_callable_call
    callee = self.infer_function_type_arguments_using_context(
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/checkexpr.py", line 1176, in infer_function_type_arguments_using_context
    args = infer_type_arguments(callable.type_var_ids(), ret_type, erased_ctx)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/infer.py", line 46, in infer_type_arguments
    return solve_constraints(type_var_ids, constraints)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/solve.py", line 71, in solve_constraints
    elif is_subtype(bottom, top):
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/subtypes.py", line 93, in is_subtype
    return _is_subtype(left, right,
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/subtypes.py", line 135, in _is_subtype
    return left.accept(SubtypeVisitor(orig_right,
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/types.py", line 1153, in accept
    return visitor.visit_callable_type(self)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/subtypes.py", line 299, in visit_callable_type
    return is_callable_compatible(
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/subtypes.py", line 839, in is_callable_compatible
    unified = unify_generic_callable(left, right, ignore_return=ignore_return)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/subtypes.py", line 1082, in unify_generic_callable
    applied = mypy.applytype.apply_generic_arguments(type, non_none_inferred_vars, report,
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/applytype.py", line 99, in apply_generic_arguments
    ret_type=expand_type(callable.ret_type, id_to_type),
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/expandtype.py", line 16, in expand_type
    return typ.accept(ExpandTypeVisitor(env))
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/types.py", line 743, in accept
    return visitor.visit_erased_type(self)
  File "/home/as/miniconda3/envs/debug_mypy/lib/python3.9/site-packages/mypy/expandtype.py", line 82, in visit_erased_type
    raise RuntimeError()
RuntimeError: 

To Reproduce

Full source code is in the description.

Your Environment

  • Mypy version used: mypy 0.820+dev.641919f9496c8c62b9f45e7ec8402162667b7a11
  • Python version used: 3.9.2
  • Operating system and version: Fedora 32

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions