Skip to content

Preserve function signatures through unannotated decorators (#3135)#3135

Closed
migeed-z wants to merge 1 commit intofacebook:mainfrom
migeed-z:export-D100840454
Closed

Preserve function signatures through unannotated decorators (#3135)#3135
migeed-z wants to merge 1 commit intofacebook:mainfrom
migeed-z:export-D100840454

Conversation

@migeed-z
Copy link
Copy Markdown
Contributor

@migeed-z migeed-z commented Apr 14, 2026

Summary:

When a decorator is fully unannotated, Pyrefly infers Unknown for all return paths, producing a union like ((dispatch_target: Unknown) -> Unknown) | Unknown. This union carries no useful type information but replaces the original function's signature, causing cascading false positives.

In this diff, we extend the heuristic as follows: if every member of the decorator's return union is "fully unknown" (either Unknown itself, or a callable where all parameters and the return type are Unknown), preserve the original function signature.

Reduces TensorFlow errors from 21,007 to 16,213 (~23% reduction, ~4,794 fewer false positives).

Differential Revision:
D100840454

#2621

D100840454

Reviewed By: grievejia

@meta-cla meta-cla bot added the cla signed label Apr 14, 2026
@meta-codesync
Copy link
Copy Markdown
Contributor

meta-codesync bot commented Apr 14, 2026

@migeed-z has exported this pull request. If you are a Meta employee, you can view the originating Diff in D100840454.

@migeed-z migeed-z closed this Apr 14, 2026
@migeed-z migeed-z reopened this Apr 14, 2026
@github-actions github-actions bot added size/m and removed size/m labels Apr 14, 2026
@meta-codesync meta-codesync bot changed the title Preserve function signatures through unannotated decorators Preserve function signatures through unannotated decorators (#3135) Apr 14, 2026
migeed-z added a commit to migeed-z/pyrefly that referenced this pull request Apr 14, 2026
…#3135)

Summary:

When a decorator is fully unannotated (e.g., TensorFlow's `make_decorator`),
Pyrefly infers `Unknown` as the return type, which erases the decorated
function's signature and causes cascading false positives for
`unexpected-keyword`, `bad-argument-count`, and `missing-argument`.

Add two fallbacks mirroring pyright's decorator handling:
1. In the union heuristic, also match `Unknown` members — if a decorator's
   return is a union containing Unknown, it likely means the decorator
   infrastructure is unannotated and the decorator is a passthrough.
2. If the decorator's return type is standalone Unknown, preserve the original
   function signature rather than erasing it.

Reduces TensorFlow errors from 21,007 to 16,809 (~20% reduction, ~4,198 fewer
false positives).

Differential Revision: D100840454
@migeed-z migeed-z force-pushed the export-D100840454 branch from e743927 to 81eec2e Compare April 14, 2026 18:51
@facebook facebook deleted a comment from github-actions bot Apr 14, 2026
@github-actions github-actions bot added size/m and removed size/m labels Apr 14, 2026
migeed-z added a commit to migeed-z/pyrefly that referenced this pull request Apr 14, 2026
…#3135)

Summary:

When a decorator is fully unannotated (e.g., TensorFlow's `make_decorator`),
Pyrefly infers `Unknown` as the return type, which erases the decorated
function's signature and causes cascading false positives for
`unexpected-keyword`, `bad-argument-count`, and `missing-argument`.

Add two fallbacks mirroring pyright's decorator handling:
1. In the union heuristic, also match `Unknown` members — if a decorator's
   return is a union containing Unknown, it likely means the decorator
   infrastructure is unannotated and the decorator is a passthrough.
2. If the decorator's return type is standalone Unknown, preserve the original
   function signature rather than erasing it.

Reduces TensorFlow errors from 21,007 to 16,809 (~20% reduction, ~4,198 fewer
false positives).

Differential Revision: D100840454
@migeed-z migeed-z force-pushed the export-D100840454 branch from 81eec2e to 8abc479 Compare April 14, 2026 19:24
@github-actions github-actions bot added size/m and removed size/m labels Apr 14, 2026
@facebook facebook deleted a comment from github-actions bot Apr 14, 2026
@facebook facebook deleted a comment from github-actions bot Apr 14, 2026
@github-actions

This comment has been minimized.

@facebook facebook deleted a comment from github-actions bot Apr 14, 2026
migeed-z added a commit to migeed-z/pyrefly that referenced this pull request Apr 14, 2026
…#3135)

Summary:



When a decorator is fully unannotated, Pyrefly infers Unknown for all return paths, producing a union like ((dispatch_target: Unknown) -> Unknown) | Unknown. This union carries no useful type information but replaces the original function's signature, causing cascading false positives.

In this diff, we extend the heuristic as follows: if every member of the decorator's return union is "fully unknown" (either Unknown itself, or a callable where all parameters and the return type are Unknown), preserve the original function signature. 

Reduces TensorFlow errors from 21,007 to 16,213 (~23% reduction, ~4,794 fewer false positives).

Differential Revision:
D100840454

facebook#2621

D100840454
@migeed-z migeed-z force-pushed the export-D100840454 branch from 8abc479 to edc8de4 Compare April 14, 2026 22:59
@github-actions github-actions bot added size/s and removed size/m labels Apr 14, 2026
@facebook facebook deleted a comment from github-actions bot Apr 14, 2026
migeed-z added a commit to migeed-z/pyrefly that referenced this pull request Apr 14, 2026
…#3135)

Summary:



When a decorator is fully unannotated, Pyrefly infers Unknown for all return paths, producing a union like ((dispatch_target: Unknown) -> Unknown) | Unknown. This union carries no useful type information but replaces the original function's signature, causing cascading false positives.

In this diff, we extend the heuristic as follows: if every member of the decorator's return union is "fully unknown" (either Unknown itself, or a callable where all parameters and the return type are Unknown), preserve the original function signature. 

Reduces TensorFlow errors from 21,007 to 16,213 (~23% reduction, ~4,794 fewer false positives).

Differential Revision:
D100840454

facebook#2621

D100840454
@migeed-z migeed-z force-pushed the export-D100840454 branch from edc8de4 to b22d1ae Compare April 14, 2026 23:16
@github-actions github-actions bot added size/s and removed size/s labels Apr 14, 2026
migeed-z added a commit to migeed-z/pyrefly that referenced this pull request Apr 14, 2026
…#3135)

Summary:



When a decorator is fully unannotated, Pyrefly infers Unknown for all return paths, producing a union like ((dispatch_target: Unknown) -> Unknown) | Unknown. This union carries no useful type information but replaces the original function's signature, causing cascading false positives.

In this diff, we extend the heuristic as follows: if every member of the decorator's return union is "fully unknown" (either Unknown itself, or a callable where all parameters and the return type are Unknown), preserve the original function signature. 

Reduces TensorFlow errors from 21,007 to 16,213 (~23% reduction, ~4,794 fewer false positives).

Differential Revision:
D100840454

facebook#2621

D100840454
@migeed-z migeed-z force-pushed the export-D100840454 branch from b22d1ae to 2d4b331 Compare April 14, 2026 23:17
@github-actions github-actions bot added size/s and removed size/s labels Apr 14, 2026
migeed-z added a commit to migeed-z/pyrefly that referenced this pull request Apr 14, 2026
…#3135)

Summary:
Pull Request resolved: facebook#3135

When a decorator is fully unannotated, Pyrefly infers Unknown for all return paths, producing a union like ((dispatch_target: Unknown) -> Unknown) | Unknown. This union carries no useful type information but replaces the original function's signature, causing cascading false positives.

In this diff, we extend the heuristic as follows: if every member of the decorator's return union is "fully unknown" (either Unknown itself, or a callable where all parameters and the return type are Unknown), preserve the original function signature.

Reduces TensorFlow errors from 21,007 to 16,213 (~23% reduction, ~4,794 fewer false positives).

Differential Revision:
D100840454

facebook#2621

D100840454
@migeed-z migeed-z force-pushed the export-D100840454 branch from 2d4b331 to ab21883 Compare April 14, 2026 23:20
@github-actions github-actions bot added size/s and removed size/s labels Apr 14, 2026
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

Copy link
Copy Markdown
Contributor

@grievejia grievejia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review automatically exported from Phabricator review in Meta.

migeed-z added a commit to migeed-z/pyrefly that referenced this pull request Apr 14, 2026
…#3135)

Summary:



When a decorator is fully unannotated, Pyrefly infers Unknown for all return paths, producing a union like ((dispatch_target: Unknown) -> Unknown) | Unknown. This union carries no useful type information but replaces the original function's signature, causing cascading false positives.

In this diff, we extend the heuristic as follows: if every member of the decorator's return union is "fully unknown" (either Unknown itself, or a callable where all parameters and the return type are Unknown), preserve the original function signature. 

Reduces TensorFlow errors from 21,007 to 16,213 (~23% reduction, ~4,794 fewer false positives).

Differential Revision:
D100840454

facebook#2621

D100840454

Reviewed By: grievejia
@migeed-z migeed-z force-pushed the export-D100840454 branch from ab21883 to 6b6a2b4 Compare April 14, 2026 23:49
@github-actions github-actions bot added size/s and removed size/s labels Apr 14, 2026
…#3135)

Summary:
Pull Request resolved: facebook#3135

When a decorator is fully unannotated, Pyrefly infers Unknown for all return paths, producing a union like ((dispatch_target: Unknown) -> Unknown) | Unknown. This union carries no useful type information but replaces the original function's signature, causing cascading false positives.

In this diff, we extend the heuristic as follows: if every member of the decorator's return union is "fully unknown" (either Unknown itself, or a callable where all parameters and the return type are Unknown), preserve the original function signature.

Reduces TensorFlow errors from 21,007 to 16,213 (~23% reduction, ~4,794 fewer false positives).

Differential Revision:
D100840454

facebook#2621

D100840454

Reviewed By: grievejia
@migeed-z migeed-z force-pushed the export-D100840454 branch from 6b6a2b4 to 7fec423 Compare April 14, 2026 23:53
@github-actions github-actions bot added size/s and removed size/s labels Apr 14, 2026
@github-actions
Copy link
Copy Markdown

Diff from mypy_primer, showing the effect of this PR on open source code:

spack (https://github.com/spack/spack)
- ERROR lib/spack/spack/build_environment.py:1624:66-88: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/ci/common.py:68:26-30: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/ci/common.py:99:26-39: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/ci/common.py:254:40-53: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/cmd/__init__.py:587:35-41: Expected 1 positional argument, got 2 [bad-argument-count]
+ ERROR lib/spack/spack/cmd/blame.py:131:22-30: Argument `Path | str` is not assignable to parameter `dirname` with type `str` in function `spack.llnl.util.filesystem.working_dir` [bad-argument-type]
+ ERROR lib/spack/spack/cmd/blame.py:261:22-28: Argument `Path | None` is not assignable to parameter `dirname` with type `str` in function `spack.llnl.util.filesystem.working_dir` [bad-argument-type]
- ERROR lib/spack/spack/cmd/ci.py:543:45-59: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/cmd/ci.py:555:55-79: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/cmd/ci.py:562:73-94: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/cmd/env.py:873:41-48: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/compilers/libraries.py:78:49-50: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/config.py:1369:50-56: Unexpected keyword argument `create` in function `spack.llnl.util.filesystem.working_dir` [unexpected-keyword]
- ERROR lib/spack/spack/environment/environment.py:2445:52-60: Unexpected keyword argument `encoding` in function `spack.llnl.util.filesystem.write_tmp_and_move` [unexpected-keyword]
- ERROR lib/spack/spack/environment/environment.py:3046:33-53: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/install_test.py:136:39-48: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/install_test.py:139:31-40: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/install_test.py:277:63-85: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/install_test.py:322:52-74: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/install_test.py:326:44-74: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/install_test.py:484:31-37: Unexpected keyword argument `create` in function `spack.llnl.util.filesystem.working_dir` [unexpected-keyword]
- ERROR lib/spack/spack/install_test.py:558:43-52: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/install_test.py:994:69-86: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/install_test.py:1056:41-68: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/installer.py:586:45-57: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/installer.py:658:35-55: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/installer.py:662:45-76: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/installer.py:689:35-41: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/installer.py:2690:48-58: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/llnl/util/filesystem.py:500:54-59: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/llnl/util/filesystem.py:699:35-56: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/llnl/util/filesystem.py:705:28-31: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/llnl/util/filesystem.py:723:15-19: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/llnl/util/filesystem.py:723:21-33: Unexpected keyword argument `_permissions` [unexpected-keyword]
- ERROR lib/spack/spack/llnl/util/filesystem.py:794:13-21: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/llnl/util/filesystem.py:795:13-18: Unexpected keyword argument `order` [unexpected-keyword]
- ERROR lib/spack/spack/llnl/util/filesystem.py:796:13-25: Unexpected keyword argument `follow_links` [unexpected-keyword]
- ERROR lib/spack/spack/llnl/util/filesystem.py:797:13-19: Unexpected keyword argument `ignore` [unexpected-keyword]
- ERROR lib/spack/spack/llnl/util/filesystem.py:798:13-31: Unexpected keyword argument `follow_nonexisting` [unexpected-keyword]
- ERROR lib/spack/spack/llnl/util/filesystem.py:829:30-31: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/llnl/util/filesystem.py:835:26-27: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/llnl/util/filesystem.py:857:20-24: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/llnl/util/filesystem.py:857:26-34: Unexpected keyword argument `symlinks` [unexpected-keyword]
- ERROR lib/spack/spack/llnl/util/filesystem.py:857:45-51: Unexpected keyword argument `ignore` [unexpected-keyword]
- ERROR lib/spack/spack/llnl/util/filesystem.py:857:60-72: Unexpected keyword argument `_permissions` [unexpected-keyword]
- ERROR lib/spack/spack/llnl/util/filesystem.py:1343:21-30: Expected 1 positional argument, got 3 [bad-argument-count]
- ERROR lib/spack/spack/llnl/util/filesystem.py:1345:21-26: Unexpected keyword argument `order` [unexpected-keyword]
- ERROR lib/spack/spack/llnl/util/filesystem.py:1346:21-27: Unexpected keyword argument `ignore` [unexpected-keyword]
- ERROR lib/spack/spack/llnl/util/filesystem.py:1347:21-39: Unexpected keyword argument `follow_nonexisting` [unexpected-keyword]
- ERROR lib/spack/spack/llnl/util/filesystem.py:1348:21-33: Unexpected keyword argument `follow_links` [unexpected-keyword]
- ERROR lib/spack/spack/llnl/util/filesystem.py:1555:39-40: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/llnl/util/filesystem.py:2435:35-41: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/llnl/util/link_tree.py:410:55-64: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/llnl/util/link_tree.py:410:66-74: Unexpected keyword argument `follow_nonexisting` [unexpected-keyword]
- ERROR lib/spack/spack/llnl/util/link_tree.py:410:66-74: Unexpected keyword argument `ignore` [unexpected-keyword]
- ERROR lib/spack/spack/llnl/util/link_tree.py:421:55-64: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/llnl/util/link_tree.py:421:66-74: Unexpected keyword argument `follow_nonexisting` [unexpected-keyword]
- ERROR lib/spack/spack/llnl/util/link_tree.py:421:66-74: Unexpected keyword argument `ignore` [unexpected-keyword]
- ERROR lib/spack/spack/llnl/util/link_tree.py:427:55-64: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/llnl/util/link_tree.py:427:66-72: Unexpected keyword argument `ignore` [unexpected-keyword]
- ERROR lib/spack/spack/llnl/util/link_tree.py:442:55-64: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/llnl/util/link_tree.py:442:66-72: Unexpected keyword argument `ignore` [unexpected-keyword]
- ERROR lib/spack/spack/llnl/util/link_tree.py:442:81-86: Unexpected keyword argument `order` [unexpected-keyword]
- ERROR lib/spack/spack/new_installer.py:636:39-45: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/new_installer.py:752:48-58: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/package_base.py:989:70-94: Expected 1 positional argument, got 2 [bad-argument-count]
+ ERROR lib/spack/spack/package_base.py:989:50-68: Argument `bool | str | tuple[bool | str, ...]` is not assignable to parameter `path` with type `str` in function `spack.llnl.util.filesystem.recursive_mtime_greater_than` [bad-argument-type]
- ERROR lib/spack/spack/paths.py:18:69-70: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/repo.py:1335:48-52: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/repo.py:1340:63-67: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/repo.py:1782:55-61: Unexpected keyword argument `create` in function `spack.llnl.util.filesystem.working_dir` [unexpected-keyword]
- ERROR lib/spack/spack/stage.py:84:63-77: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/stage.py:831:39-55: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/stage.py:833:34-50: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/binary_distribution.py:508:29-34: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/binary_distribution.py:509:29-39: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/binary_distribution.py:510:29-40: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/cmd/buildcache.py:548:32-48: Expected 1 positional argument, got 2 [bad-argument-count]
+ ERROR lib/spack/spack/test/cmd/buildcache.py:548:32-48: Argument `Path` is not assignable to parameter `dest` with type `str` in function `spack.llnl.util.filesystem.copy_tree` [bad-argument-type]
+ ERROR lib/spack/spack/test/cmd/ci.py:610:22-41: Argument `Path` is not assignable to parameter `dirname` with type `str` in function `spack.llnl.util.filesystem.working_dir` [bad-argument-type]
+ ERROR lib/spack/spack/test/cmd/ci.py:655:22-41: Argument `Path` is not assignable to parameter `dirname` with type `str` in function `spack.llnl.util.filesystem.working_dir` [bad-argument-type]
+ ERROR lib/spack/spack/test/cmd/ci.py:742:22-30: Argument `Path` is not assignable to parameter `dirname` with type `str` in function `spack.llnl.util.filesystem.working_dir` [bad-argument-type]
+ ERROR lib/spack/spack/test/cmd/ci.py:784:22-30: Argument `Path` is not assignable to parameter `dirname` with type `str` in function `spack.llnl.util.filesystem.working_dir` [bad-argument-type]
+ ERROR lib/spack/spack/test/cmd/ci.py:1083:22-30: Argument `Path` is not assignable to parameter `dirname` with type `str` in function `spack.llnl.util.filesystem.working_dir` [bad-argument-type]
+ ERROR lib/spack/spack/test/cmd/ci.py:1214:22-30: Argument `Path` is not assignable to parameter `dirname` with type `str` in function `spack.llnl.util.filesystem.working_dir` [bad-argument-type]
+ ERROR lib/spack/spack/test/cmd/ci.py:1279:22-30: Argument `Path` is not assignable to parameter `dirname` with type `str` in function `spack.llnl.util.filesystem.working_dir` [bad-argument-type]
+ ERROR lib/spack/spack/test/cmd/ci.py:1378:22-30: Argument `Path` is not assignable to parameter `dirname` with type `str` in function `spack.llnl.util.filesystem.working_dir` [bad-argument-type]
+ ERROR lib/spack/spack/test/cmd/ci.py:1383:26-34: Argument `Path` is not assignable to parameter `dirname` with type `str` in function `spack.llnl.util.filesystem.working_dir` [bad-argument-type]
- ERROR lib/spack/spack/test/cmd/clean.py:80:45-58: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/cmd/clean.py:82:42-53: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/cmd/clean.py:83:42-56: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/cmd/clean.py:86:46-54: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/cmd/clean.py:91:55-66: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/cmd/clean.py:92:59-73: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/cmd/clean.py:93:59-72: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/cmd/clean.py:95:46-51: Expected 1 positional argument, got 4 [bad-argument-count]
- ERROR lib/spack/spack/test/cmd/clean.py:96:43-48: Expected 1 positional argument, got 4 [bad-argument-count]
- ERROR lib/spack/spack/test/cmd/env.py:1533:33-46: Expected 1 positional argument, got 2 [bad-argument-count]
+ ERROR lib/spack/spack/test/cmd/env.py:219:29-37: Argument `Path` is not assignable to parameter `dirname` with type `str` in function `spack.llnl.util.filesystem.working_dir` [bad-argument-type]
- ERROR lib/spack/spack/test/cmd/install.py:246:51-57: Unexpected keyword argument `ignore` [unexpected-keyword]
- ERROR lib/spack/spack/test/cmd/install.py:253:46-52: Unexpected keyword argument `ignore` [unexpected-keyword]
- ERROR lib/spack/spack/test/cmd/install.py:260:43-49: Unexpected keyword argument `ignore` [unexpected-keyword]
- ERROR lib/spack/spack/test/cmd/install.py:261:43-49: Unexpected keyword argument `ignore` [unexpected-keyword]
- ERROR lib/spack/spack/test/cmd/install.py:317:64-70: Unexpected keyword argument `ignore` [unexpected-keyword]
- ERROR lib/spack/spack/test/cmd/install.py:327:58-64: Unexpected keyword argument `ignore` [unexpected-keyword]
- ERROR lib/spack/spack/test/cmd/install.py:336:59-65: Unexpected keyword argument `ignore` [unexpected-keyword]
- ERROR lib/spack/spack/test/cmd/install.py:337:53-59: Unexpected keyword argument `ignore` [unexpected-keyword]
- ERROR lib/spack/spack/test/cmd/install.py:346:50-56: Unexpected keyword argument `ignore` [unexpected-keyword]
- ERROR lib/spack/spack/test/cmd/install.py:347:47-53: Unexpected keyword argument `ignore` [unexpected-keyword]
- ERROR lib/spack/spack/test/cmd/test.py:232:30-45: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/config.py:1520:41-52: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/config.py:1531:41-52: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/config.py:1884:45-51: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/config.py:1998:53-59: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/conftest.py:1203:36-52: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/conftest.py:1240:33-48: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/conftest.py:2217:36-44: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/conftest.py:2218:36-44: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/conftest.py:2219:19-23: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/conftest.py:2485:47-59: Expected 1 positional argument, got 3 [bad-argument-count]
- ERROR lib/spack/spack/test/install.py:482:30-34: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:57:33-41: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:65:33-39: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:73:37-43: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:83:40-46: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:92:41-49: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:110:36-44: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:119:36-42: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:128:40-46: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:140:43-49: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:149:44-52: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:159:36-42: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:167:36-56: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:175:36-42: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:175:44-52: Unexpected keyword argument `symlinks` [unexpected-keyword]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:191:36-42: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:191:44-52: Unexpected keyword argument `symlinks` [unexpected-keyword]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:191:59-65: Unexpected keyword argument `ignore` [unexpected-keyword]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:200:36-42: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:200:44-52: Unexpected keyword argument `symlinks` [unexpected-keyword]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:210:40-46: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:221:45-51: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:229:40-62: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:239:39-45: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:248:39-59: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:257:39-45: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:257:47-55: Unexpected keyword argument `symlinks` [unexpected-keyword]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:268:39-45: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:268:47-55: Unexpected keyword argument `symlinks` [unexpected-keyword]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:280:39-45: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:280:47-55: Unexpected keyword argument `symlinks` [unexpected-keyword]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:288:43-49: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:302:48-54: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:310:43-65: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:470:36-41: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:712:41-51: Expected 1 positional argument, got 2 in function `spack.llnl.util.filesystem.safe_remove` [bad-argument-count]
- ERROR lib/spack/spack/test/llnl/util/filesystem.py:732:48-58: Expected 1 positional argument, got 3 in function `spack.llnl.util.filesystem.keep_modification_time` [bad-argument-count]
+ ERROR lib/spack/spack/test/llnl/util/filesystem.py:1034:27-52: Argument `Literal['C:\\Program Files (x86)']` is not assignable to parameter `path` with type `PathLike[Unknown]` in function `spack.llnl.util.filesystem.windows_sfn` [bad-argument-type]
+ ERROR lib/spack/spack/test/llnl/util/filesystem.py:1036:27-44: Argument `Literal['C:\\ProgramData']` is not assignable to parameter `path` with type `PathLike[Unknown]` in function `spack.llnl.util.filesystem.windows_sfn` [bad-argument-type]
+ ERROR lib/spack/spack/test/llnl/util/filesystem.py:1057:12-64: `in` is not supported between `Literal['d\\THISIS~1\\a\\STILLT~1']` and `PathLike[Unknown]` [not-iterable]
+ ERROR lib/spack/spack/test/llnl/util/filesystem.py:1057:57-63: Argument `str` is not assignable to parameter `path` with type `PathLike[Unknown]` in function `spack.llnl.util.filesystem.windows_sfn` [bad-argument-type]
+ ERROR lib/spack/spack/test/llnl/util/filesystem.py:1058:12-61: `in` is not supported between `Literal['d\\LONG_P~1\\MORE_L~1']` and `PathLike[Unknown]` [not-iterable]
+ ERROR lib/spack/spack/test/llnl/util/filesystem.py:1058:54-60: Argument `str` is not assignable to parameter `path` with type `PathLike[Unknown]` in function `spack.llnl.util.filesystem.windows_sfn` [bad-argument-type]
+ ERROR lib/spack/spack/test/llnl/util/filesystem.py:1059:12-58: `in` is not supported between `Literal['d\\this\\is\\short']` and `PathLike[Unknown]` [not-iterable]
+ ERROR lib/spack/spack/test/llnl/util/filesystem.py:1059:51-57: Argument `str` is not assignable to parameter `path` with type `PathLike[Unknown]` in function `spack.llnl.util.filesystem.windows_sfn` [bad-argument-type]
+ ERROR lib/spack/spack/test/llnl/util/filesystem.py:1060:12-51: `in` is not supported between `Literal['d\\LONGER~1']` and `PathLike[Unknown]` [not-iterable]
+ ERROR lib/spack/spack/test/llnl/util/filesystem.py:1060:44-50: Argument `str` is not assignable to parameter `path` with type `PathLike[Unknown]` in function `spack.llnl.util.filesystem.windows_sfn` [bad-argument-type]
+ ERROR lib/spack/spack/test/llnl/util/filesystem.py:1061:12-51: `in` is not supported between `Literal['d\\LONGER~2']` and `PathLike[Unknown]` [not-iterable]
+ ERROR lib/spack/spack/test/llnl/util/filesystem.py:1061:44-50: Argument `str` is not assignable to parameter `path` with type `PathLike[Unknown]` in function `spack.llnl.util.filesystem.windows_sfn` [bad-argument-type]
- ERROR lib/spack/spack/test/main.py:264:66-78: Expected 1 positional argument, got 2 [bad-argument-count]
+ ERROR lib/spack/spack/test/mirror.py:433:22-28: Argument `Path` is not assignable to parameter `dirname` with type `str` in function `spack.llnl.util.filesystem.working_dir` [bad-argument-type]
- ERROR lib/spack/spack/test/package_class.py:202:39-42: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/package_class.py:217:42-45: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/package_class.py:218:42-43: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/reporters.py:18:5-10: Expected 1 positional argument, got 9 [bad-argument-count]
- ERROR lib/spack/spack/test/reporters.py:27:60-68: Expected 1 positional argument, got 3 [bad-argument-count]
- ERROR lib/spack/spack/test/reporters.py:29:12-19: Expected 1 positional argument, got 8 [bad-argument-count]
- ERROR lib/spack/spack/test/reporters.py:35:50-55: Expected 1 positional argument, got 3 [bad-argument-count]
- ERROR lib/spack/spack/test/reporters.py:81:50-55: Expected 1 positional argument, got 3 [bad-argument-count]
- ERROR lib/spack/spack/test/stage.py:366:81-85: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/util/file_cache.py:89:40-60: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/util/file_cache.py:111:41-60: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/util/git.py:40:60-66: Unexpected keyword argument `create` in function `spack.llnl.util.filesystem.working_dir` [unexpected-keyword]
- ERROR lib/spack/spack/test/util/git.py:51:35-41: Unexpected keyword argument `create` in function `spack.llnl.util.filesystem.working_dir` [unexpected-keyword]
- ERROR lib/spack/spack/test/util/git.py:63:35-41: Unexpected keyword argument `create` in function `spack.llnl.util.filesystem.working_dir` [unexpected-keyword]
- ERROR lib/spack/spack/test/util/git.py:74:35-41: Unexpected keyword argument `create` in function `spack.llnl.util.filesystem.working_dir` [unexpected-keyword]
- ERROR lib/spack/spack/test/util/git.py:85:35-41: Unexpected keyword argument `create` in function `spack.llnl.util.filesystem.working_dir` [unexpected-keyword]
- ERROR lib/spack/spack/test/util/remote_file_cache.py:69:53-66: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/test/util/remote_file_cache.py:97:41-48: Expected 1 positional argument, got 2 [bad-argument-count]
- ERROR lib/spack/spack/util/remote_file_cache.py:124:44-52: Expected 1 positional argument, got 2 [bad-argument-count]

... (truncated 5 lines) ...

@github-actions
Copy link
Copy Markdown

Primer Diff Classification

✅ 1 improvement(s) | 1 project(s) total | +27, -166 errors

1 improvement(s) across spack.

Project Verdict Changes Error Kinds Root Cause
spack ✅ Improvement +27, -166 Removed false positive bad-argument-count errors (121) apply_decorator()
Detailed analysis

✅ Improvement (1)

spack (+27, -166)

Removed false positive bad-argument-count errors (121): These errors incorrectly claimed wrong argument counts for functions like copy, join_path, and working_dir because unannotated decorators destroyed their signatures. The functions do accept the arguments being passed. Removing these is an improvement.
Removed false positive unexpected-keyword errors (45): These errors incorrectly claimed keywords like create were invalid for working_dir. The function does accept this keyword. The errors existed because the decorator stripped the signature. Removing these is an improvement.
New bad-argument-type errors (22): Now that pyrefly preserves function signatures through unannotated decorators, it can see that e.g. working_dir(dirname: str) expects str but callers pass Path | str. All 22 are confirmed by pyright. These are real type narrowness issues — improvement.
New not-iterable errors (5): In test file, checking membership (in) against PathLike[Unknown] which doesn't support __contains__ or iteration. All 5 confirmed by pyright. These are real type issues revealed by better signature preservation — improvement.

Overall: This is a clear improvement. The PR fixes a significant inference problem where unannotated decorators destroyed function signatures, causing 166 false positive errors. By preserving original signatures through unknown decorators, pyrefly now correctly understands the parameter lists and types of these functions. The 27 new errors are genuine type issues (confirmed by pyright 27/27) that were previously invisible because pyrefly couldn't see the function signatures at all. Net result: 139 fewer errors, with the remaining new errors being real type narrowness issues (e.g., passing Path | str where str is expected).

Per-category reasoning:

  • Removed false positive bad-argument-count errors (121): These errors incorrectly claimed wrong argument counts for functions like copy, join_path, and working_dir because unannotated decorators destroyed their signatures. The functions do accept the arguments being passed. Removing these is an improvement.
  • Removed false positive unexpected-keyword errors (45): These errors incorrectly claimed keywords like create were invalid for working_dir. The function does accept this keyword. The errors existed because the decorator stripped the signature. Removing these is an improvement.
  • New bad-argument-type errors (22): Now that pyrefly preserves function signatures through unannotated decorators, it can see that e.g. working_dir(dirname: str) expects str but callers pass Path | str. All 22 are confirmed by pyright. These are real type narrowness issues — improvement.
  • New not-iterable errors (5): In test file, checking membership (in) against PathLike[Unknown] which doesn't support __contains__ or iteration. All 5 confirmed by pyright. These are real type issues revealed by better signature preservation — improvement.

Attribution: The change to apply_decorator() in pyrefly/lib/alt/function.rs (lines adding the Type::Union match arm that checks is_fully_unknown()) and the new is_fully_unknown() method in crates/pyrefly_types/src/callable.rs together cause this. Previously, unannotated decorators produced a union of Unknown callables that replaced the original signature. Now, when all union members are fully unknown, the original function signature is preserved. This removes 166 false positives (pyrefly can now see the real signatures of decorated functions like working_dir, copy, join_path) and reveals 27 real type issues that were previously masked.


Was this helpful? React with 👍 or 👎

Classification by primer-classifier (1 LLM)

@meta-codesync
Copy link
Copy Markdown
Contributor

meta-codesync bot commented Apr 15, 2026

This pull request has been merged in e736f68.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants