[ty] Full-scope bidirectional inference for unconstrained container literals by ibraheemdev · Pull Request #25279 · astral-sh/ruff (original) (raw)

@ibraheemdev

ibraheemdev

ibraheemdev

carljm

@ibraheemdev

thejchap pushed a commit to thejchap/ruff that referenced this pull request

May 23, 2026

@ibraheemdev @thejchap

…iterals (astral-sh#25279)

Implements full-scope bidirectional inference for collection literals that are not constrained at their definition, e.g.,

x = []
x.append(1)
x.append("2")
reveal_type(x)  # revealed: list[int | str]

In particular, this PR considers empty, unannotated collection literals to be unconstrained, e.g., lst = [], and looks ahead in their containing scope for potentially constraining uses, which are:

The inferred type of the collection literal is the union of all constraints on the element type, collected from all constraining uses in the containing scope. Note that operations through reassignments, arbitrary function calls, augmented assignments, nested bound-method calls, etc., are not currently tracked.

Note that because this PR only considers unconstrained collection literals, for which we previously inferred Unknown types, the ecosystem report consists primarily of new diagnostics. These are ideally removing false negatives, but likely introduces many false positives as well, because the heuristic implemented is not perfect. However, this approach is quite easily extended to unannotated collection literals that are not empty, which seems to remove a couple hundred ecosystem diagnostics, but I'd like to intentionally limit the scope of this change (and the performance/memory usage impact).

Part of astral-sh/ty#1473.

anishgirianish pushed a commit to anishgirianish/ruff that referenced this pull request

May 28, 2026

@ibraheemdev @anishgirianish

…iterals (astral-sh#25279)

Implements full-scope bidirectional inference for collection literals that are not constrained at their definition, e.g.,

x = []
x.append(1)
x.append("2")
reveal_type(x)  # revealed: list[int | str]

In particular, this PR considers empty, unannotated collection literals to be unconstrained, e.g., lst = [], and looks ahead in their containing scope for potentially constraining uses, which are:

The inferred type of the collection literal is the union of all constraints on the element type, collected from all constraining uses in the containing scope. Note that operations through reassignments, arbitrary function calls, augmented assignments, nested bound-method calls, etc., are not currently tracked.

Note that because this PR only considers unconstrained collection literals, for which we previously inferred Unknown types, the ecosystem report consists primarily of new diagnostics. These are ideally removing false negatives, but likely introduces many false positives as well, because the heuristic implemented is not perfect. However, this approach is quite easily extended to unannotated collection literals that are not empty, which seems to remove a couple hundred ecosystem diagnostics, but I'd like to intentionally limit the scope of this change (and the performance/memory usage impact).

Part of astral-sh/ty#1473.

ibraheemdev added a commit that referenced this pull request

Jun 15, 2026

@ibraheemdev

…rals (#25280)

Extends #25279 to support full-scope inference for all unannotated collection literals, even those that are non-empty, e.g.,

x = [1]
x.append("2")
reveal_type(x) # revealed: list[int | str]

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters

[ Show hidden characters]({{ revealButtonHref }})