Repository navigation
[tensor-shapes] torch stubs 1.4.0.dev3: missing channels_last/uint8/FloatTensor/unique, parameters() yields Tensor, and other false positives #5161
Description
Describe the Bug
With pyrefly-torch-stubs 1.4.0.dev3 (and the matching pyrefly and pyrefly-shape-extensions 1.4.0.dev3), pyrefly reports errors on ordinary PyTorch code that runs without error. We found these while we evaluated the stubs on two research codebases (Python 3.10; torch 2.4.1 and torch 2.6.0). They are not in #3380.
The repro below runs cleanly with python repro.py (torch 2.6.0, Python 3.10.20). With the minimal pyrefly.toml below next to it, pyrefly check reports the 11 errors listed further down. Without a config file, pyrefly falls back to the basic preset and reports 0 errors, which hides the problem.
project-includes = ["repro.py"]
python-interpreter-path = ".venv/bin/python" # the venv with torch and the stubs installedrepro.py:
import torch
from torch import nn
model = nn.Linear(2, 2)
# 1. Missing module attributes (all exist at runtime).
fmt = torch.channels_last
dt = torch.uint8
ft: torch.FloatTensor
u = torch.unique(torch.tensor([1, 1, 2]))
# 2. named_parameters() / parameters() should yield Parameter, not Tensor.
def takes_param(p: nn.Parameter) -> None: ...
for _, p in model.named_parameters():
takes_param(p)
for p in model.parameters():
takes_param(p)
# 3. Tensor-scalar comparison should return Tensor, not bool.
mask = torch.zeros(3) != 0.0
mask.float()
torch.all(torch.zeros(3) == 0.0)
# 4. AdaptiveAvgPool2d accepts an int output_size.
pool = nn.AdaptiveAvgPool2d(1)
# 5. torch.randint(high, size) positional form.
r = torch.randint(10, (1,))
# 6. torch.is_tensor should narrow (torch itself annotates it as TypeIs[Tensor]).
def f(m: float | torch.Tensor, i: torch.Tensor) -> None:
if torch.is_tensor(m):
m[i]ERROR No attribute `channels_last` in module `torch` [missing-attribute] # line 7
ERROR No attribute `uint8` in module `torch` [missing-attribute] # line 8
ERROR No attribute `FloatTensor` in module `torch` [missing-attribute] # line 9
ERROR No attribute `unique` in module `torch` [missing-attribute] # line 10
ERROR Argument `Tensor` is not assignable to parameter `p` with type `Parameter` in function `takes_param` [bad-argument-type] # lines 15, 17
ERROR Object of class `bool` has no attribute `float` [missing-attribute] # line 21
ERROR Argument `bool` is not assignable to parameter `input` with type `Tensor[@_]` in function `torch.all` [bad-argument-type] # line 22
ERROR Argument `Literal[1]` is not assignable to parameter `output_size` with type `tuple[Int[@_], Int[@_]]` in function `torch.nn.AdaptiveAvgPool2d.__init__` [bad-argument-type] # line 25
ERROR Missing argument `size` in function `torch.randint` [missing-argument] # line 28
ERROR Cannot index into `float` [bad-index] # line 33
Expected: no errors. Summary of the gaps:
torch.channels_last,torch.uint8,torch.FloatTensorandtorch.uniqueare missing from the module.Module.named_parameters()andModule.parameters()yieldTensor, notnn.Parameter.Tensor.__eq__/Tensor.__ne__with a Python scalar returnbool, notTensor.nn.AdaptiveAvgPool2drejects anintoutput_size.- The
torch.randint(high, size)overload (withoutlow) is missing. torch.is_tensorreturnsbool. torch itself annotates it asTypeIs[Tensor], so the stubs lose narrowing.
The missing torch.FloatTensor has a knock-on effect. Hugging Face transformers output dataclasses annotate fields as Optional[torch.FloatTensor], for example BaseModelOutput.last_hidden_state. With the stubs installed, those fields become Unknown | None, so outputs.last_hidden_state[:, 1:] reports "None is not subscriptable" in user code.
Versions: pyrefly 1.4.0.dev3, pyrefly-torch-stubs 1.4.0.dev3, pyrefly-shape-extensions 1.4.0.dev3, torch 2.6.0 (also seen with 2.4.1), Python 3.10.20, Linux x86_64.
Sandbox Link
No response
(Only applicable for extension issues) IDE Information
No response
Activity
stroxler commentedon Oct 9, 2026
Thanks for the bug report!
Just to make sure I understood a few things correctly...
I think for (2) you're saying it actually yields
Parameter, but our stubs incorrectly sayTensor, is that right? I fixed this and added a test that seems to show torch actually givesParameter.For (3), I think the issue was already fixed on trunk although this did help me diagnose and fix a separate issue where we were producing a gradual-shape
Tensorinstead of understanding that comparison with a scalar gives us back the shape ofSelf.stroxler commentedon Oct 9, 2026
Should be fixed in the next release. I'm not sure whether I'll have time to make another dev release, but 1.4.0 should be coming out next week
Narrow values with `torch.is_tensor`