python / python/mypy

ENH: Support slack variables (lower bound emulation)

Open
#20,648 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

Describe the Bug

Context: https://github.com/python/typing/issues/674

Slack variables would allow us to emulate lower bounds on type variables, which is relevant for methods like dict.__or__ or list concatenation, when an outer context is present.

from typing import Never, assert_type, reveal_type

class Vec[T]:  # invariant in T
    def _items(self) -> list[T]: ...
    def _append(self, item: T) -> None: ...

def concat_vecs[T1, T2, _T_slack=Never](
    left: Vec[T1],
    right: Vec[T2],
) -> Vec[T1 | T2 | _T_slack]:  # <-- Slack variable makes return a supertype of T1 | T2
    return Vec()

class A: ...
class B: ...
class C: ...

def test_vec_concat(left: Vec[A], right: Vec[B]) -> None:
    # without outer context, the type is precise
    assert_type(concat_vecs(left, right), Vec[A | B])  # ✅️
    # outer context allows widening due to slack variables
    _0: Vec[A | B]     = concat_vecs(left, right) # ❌️
    _1: Vec[A | B | C] = concat_vecs(left, right) # ❌️
    _2: Vec[object]    = concat_vecs(left, right) # ❌️

mypy fails to find existing solutions on some of these function calls:

  • _0: (T1=A, T2=B, _T_slack=Never)
  • _1: (T1=A, T2=B, _T_slack=C)
  • _2: (T1=A, T2=B, _T_slack=object)
21:38: error: Argument 1 to "concat_vecs" has incompatible type "Vec[A]"; expected "Vec[A | B]"  [arg-type]
21:44: error: Argument 2 to "concat_vecs" has incompatible type "Vec[B]"; expected "Vec[A | B]"  [arg-type]
22:38: error: Argument 1 to "concat_vecs" has incompatible type "Vec[A]"; expected "Vec[A | B | C]"  [arg-type]
22:44: error: Argument 2 to "concat_vecs" has incompatible type "Vec[B]"; expected "Vec[A | B | C]"  [arg-type]
23:38: error: Argument 1 to "concat_vecs" has incompatible type "Vec[A]"; expected "Vec[object]"  [arg-type]
23:44: error: Argument 2 to "concat_vecs" has incompatible type "Vec[B]"; expected "Vec[object]"  [arg-type]

no playground link as typevar defaults are still not supported.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Vec and concat_vecs reproduction in the issue, then read the linked python/typing issue 674 for the slack-variable context. No repository files or tests are named; done means the _0, _1, and _2 calls type-check with the stated widened result types.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
devtools
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.