Invariant code expecting to combine seperate types into union stops working wih indirection
- Dominant language
- Rust
- Stars
- 7k
- Forks
- 519
- PR merge metrics
- No merged PRs in 30d
Description
### Describe the Bug
When pyrefly is solving a generic function with an invariant type parameter, I expect that it always behaves the same (the same generic over different parameters is solved to a union if available).
Instead, the behavior is inconsistent between one with no indirection, and one level of call indirection, where if the arguments are put behind a level of call indirection, pyrefly stops inferring the union solution and instead gives an error.
```py
from collections.abc import Callable
from typing import Literal
class Container[T]:
def get(self) -> T: ...
def combine[T](*args: Container[T]) -> Container[T]: ...
# Code works fine with no indirection (no errors)
x: Container[int | str] = combine(
Container[int](),
Container[str](),
)
def indirection[T](c: Container[T]) -> Container[T]:
return c
# With an added level of indirection, the code stops working
# ERROR sandbox.py:24:5-42: Argument `Container[str]` is not assignable to parameter `*args` with type `Container[int]` in function `combine` [bad-argument-type]
y: Container[int | str] = combine(
indirection(Container[int]()),
indirection(Container[str]()),
)
```
### Sandbox Link
https://pyrefly.org/sandbox/?project=v2.jVVda4MwFP0rF_qgG1WhuBffxtjzhhT2UApaDVrWmqLpuv37nZvENemK7aMx5yb3no9MRuaNFLHh4AerzUbmaTTci-wU7ir61XLtuK4RSptEi2SZURzHBsU_K7nfAAJE-AhvwMluFQ3xyp7RM_yoBZ1k_zkgmmCZ01a11EnIxU4c5IT4NpxAK99udWgIXuPIwMDtNUJza2_TOnyYXy4zSi9rnZpOnFO5m-pWJ1Z2xnzV2NMH91BCnXUtatoh8nckveJzUq3AhdH7oORh0BMAMYx-zfO3nM4EZ4s0e4rSRUbPfXPcC7Rc-F0UnCMQIj89UCbTTUpC-D08Coap0LQUZrj89rgVeDyo0P1lGRV2kgWtNmUdAauPjRgJV_zcyYDTb3jJxkjH9T2GGsvNf-_O6N0sjFPCwTB9c8TbiELQ1gzPoqBWqcOQJckIl32TiC6pZTUkHiIhjqnyq9xqr_jlSOqsGVD2emikd4VGYDIjmIqMgBMDOyZT4Bc
### (Only applicable for extension issues) IDE Information
_No response_
Contributor guide
Research direction
Reproduce the two combine examples from the linked Pyrefly sandbox, comparing direct Container arguments with the indirection function. Trace the invariant generic inference path for these calls; done means both forms infer Container[int | str] without the reported bad-argument-type error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, rust
- Domain
- compilers, devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100