Skip to content

False positive [invalid-assignment] on assigning to union with bounded typevar #2314

@randolf-scholz

Description

@randolf-scholz

Summary

https://play.ty.dev/b3098a7e-d5ce-480f-be95-3f4cd7a6d224

def upcast(arg: int) -> int:
    return arg

def test[X: int](items: list[X]) -> list[X]:
    _a: list[int] = list(items)           # ✅️
    _b: list[int] = [*items]              # ✅️
    _c: list[int] = [x for x in items]    # ✅️

    _1: list[str] | list[int] = list(items)         # ❌️
    _2: list[int] | list[str] = list(items)         # ❌️
    _3: list[str] | list[int] = [*items]            # ✅️
    _4: list[int] | list[str] = [*items]            # ✅️
    _5: list[str] | list[int] = [x for x in items]  # ✅️
    _6: list[int] | list[str] = [x for x in items]  # ✅️
    _7: list[str] | list[int] = [upcast(x) for x in items]  # ✅️
    _8: list[int] | list[str] = [upcast(x) for x in items]  # ✅️
    return items

This reports

Object of type list[X@test] is not assignable to `list[str] | list[int]

But at the same time, it reports list is [T] (Iterable[T]) -> list[T].

So in _1 and _2 we have joint constraints:

  • X <: T (list[X] must be assignable to Iterable[T]),
  • X <: int upper bound
  • T = int or T=str (list[T] <: list[int] | list[str])

So, this has the unique solution T=int, but ty seems to incorrectly select T=X.

Metadata

Metadata

Assignees

Labels

bidirectional inferenceInference of types that takes into account the context of a declared type or expected typegenericsBugs or features relating to ty's generics implementation

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions