Skip to content

fix emit unused parameter #955#1447

Closed
asukaminato0721 wants to merge 4 commits into
facebook:mainfrom
asukaminato0721:955
Closed

fix emit unused parameter #955#1447
asukaminato0721 wants to merge 4 commits into
facebook:mainfrom
asukaminato0721:955

Conversation

@asukaminato0721

@asukaminato0721 asukaminato0721 commented Nov 1, 2025

Copy link
Copy Markdown
Collaborator

part of #955

callable_infer now records not only the expected parameter type for each call argument, but also which parameter index the argument matched.

Overload “No matching overload” diagnostics use that real argument-to-parameter mapping instead of reconstructing it from positional counts / keyword names.

If the failure is missing required args, show the full required signature so users can see what to pass, e.g. z / w.
If the failure is wrong argument type, truncate unrelated optional params with ... so the relevant parameters stand out.

@meta-cla meta-cla Bot added the cla signed label Nov 1, 2025
@asukaminato0721 asukaminato0721 changed the title make cli overlaod error have newline make cli overload error have newline Nov 1, 2025
@asukaminato0721
asukaminato0721 marked this pull request as ready for review November 2, 2025 17:10
@stroxler
stroxler requested a review from rchen152 November 3, 2025 15:41
@rchen152

rchen152 commented Nov 4, 2025

Copy link
Copy Markdown
Contributor

I'm a little worried about how long this would make the [no-matching-overload] error message. I agree that the line breaks make the individual signatures more readable, but this could easily turn, say, a 10-line message into a 100-line one. And I assume the syntax highlighting doesn't show up unless you do an extra step of piping to bat, so it wouldn't be there by default to help with parsing the output?

I wonder if it would be better to instead implement the other suggestion in #955, hiding unrelated fields. That could make these messages more readable without increasing their length.

@rchen152 rchen152 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Marking this as "Changes requested", since I don't think we can merge it as-is. My main concern is about error message length, but looking more closely at the PR, it also puts the # [closest match] comment in an odd place, so that would need to be fixed as well.

@rchen152 rchen152 removed their assignment Nov 17, 2025
Copilot AI review requested due to automatic review settings February 5, 2026 18:11

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR improves the readability of CLI overload error messages by formatting them as syntactically valid Python code that can be piped to syntax highlighters like bat. The changes enable better visualization of long, complex overload signatures by marking the "[closest match]" indicator as a Python comment.

Changes:

  • Changed the overload closest match marker from " [closest match]" to "# [closest match]" to make it a Python comment
  • Updated test expectations to reflect the new formatting that includes def prefix, newlines for parameters, and proper Python syntax
  • Updated conformance test expectations across multiple test cases to match the new format

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
pyrefly/lib/alt/overload.rs Changed closest match suffix from space-prefixed to hash-prefixed to create a valid Python comment
pyrefly/lib/test/overload.rs Updated test expectation to match new multi-line format with Python syntax
conformance/third_party/conformance.exp Updated multiple test expectations to reflect new overload formatting with def syntax and comment markers

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions

This comment has been minimized.

@asukaminato0721 asukaminato0721 changed the title make cli overload error have newline fix emit unused parameter #955 Feb 5, 2026
@github-actions

This comment has been minimized.

@asukaminato0721

Copy link
Copy Markdown
Collaborator Author

this will be much shorter

 --> /tmp/tmp/main.py:9:2
  |
9 | f(1, 2)
  |  ^^^^^^
  |
  Possible overloads:
  (x: int, y: int, ...) -> int [closest match]
  (x: str, y: str, ...) -> str
 INFO 1 error

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@yangdanny97
yangdanny97 requested a review from rchen152 April 3, 2026 18:23
@yangdanny97

Copy link
Copy Markdown
Contributor

i'm gonna re-trigger CI

Comment thread pyrefly/lib/test/overload.rs Outdated
def f(x: str, y: str, z: str, w: str) -> str: ...
def f(x, y, z=None, w=None): return x

f(1, 2) # E: (x: int, y: int, ...) -> int [missing required arguments] # !E: z: # !E: w:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Omitting z and w here doesn't seem like an improvement. Since the error is that they're missing, we should show them so that the user can see what arguments they need to pass in and in what order.

IMO the obvious case in which it would be useful to omit parameters would a wrong argument type error, in which the user has passed in the right number of arguments but one or more has the wrong type, so we want the error message to highlight those.

Comment thread pyrefly/lib/alt/overload.rs Outdated
return full_signature();
};

let mut positional_remaining = args

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reconstructing the argument->parameter mapping for error reporting seems inefficient and error-prone. We already return the mapping from callable_infer, so it would be nice if we could reuse it:

HashMap<TextRange, Type>,

@kinto0

kinto0 commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

is this still relevant with our current error messages?

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@meta-codesync

meta-codesync Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

@rchen152 has imported this pull request. If you are a Meta employee, you can view this in D107938504.

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

@rchen152

Copy link
Copy Markdown
Contributor

Sorry for the delayed response here! I ended up taking a different approach to this issue, in #3782. The key differences are that that PR has a narrower focus (just omits irrelevant parameter types, doesn't try to do any handling of other kinds of call errors), reuses the existing signature display code, tracks parameters by name instead of index, and filters all overload signatures rather than just the closest one. I'm going to close this PR now, but thank you for all of your contributions. Apologies again for sitting on this for so long.

@rchen152 rchen152 closed this Jun 11, 2026
@asukaminato0721
asukaminato0721 deleted the 955 branch June 12, 2026 01:28
meta-codesync Bot pushed a commit that referenced this pull request Jun 12, 2026
Summary:
No functional change. I'm planning to add more info to this map, so let's first rename it and make it more structured.

Context:

This stack is a ground-up re-implementation of #1447. It has a narrower focus (just omits irrelevant parameter types, doesn't try to do any handling of other kinds of call errors), reuses the existing signature display code, tracks parameters by name instead of index, and filters all overload signatures rather than just the closest one.

Reviewed By: grievejia

Differential Revision: D108230388

fbshipit-source-id: 3a7f63d9143cc2767566f414b7994e4eff015d5c
meta-codesync Bot pushed a commit that referenced this pull request Jun 12, 2026
Summary:
No functional change. This will be needed to accurately map keyword arguments to their corresponding parameters.

Context:

This stack is a ground-up re-implementation of #1447. It has a narrower focus (just omits irrelevant parameter types, doesn't try to do any handling of other kinds of call errors), reuses the existing signature display code, tracks parameters by name instead of index, and filters all overload signatures rather than just the closest one.

Reviewed By: grievejia

Differential Revision: D108230391

fbshipit-source-id: 32b3ded028ee5349cd750ca3a8880b20604e84f9
meta-codesync Bot pushed a commit that referenced this pull request Jun 12, 2026
Summary:
Adds parameter names to the map that callable_infer builds from arguments to matched parameters. This will be used to improve signature printing in no-matching-overload errors.

No functional change.

Context:

This stack is a ground-up re-implementation of #1447. It has a narrower focus (just omits irrelevant parameter types, doesn't try to do any handling of other kinds of call errors), reuses the existing signature display code, tracks parameters by name instead of index, and filters all overload signatures rather than just the closest one.

Reviewed By: grievejia

Differential Revision: D108230387

fbshipit-source-id: b7eda2ffbbf6904e3324f96eff0d7e12c97ad951
meta-codesync Bot pushed a commit that referenced this pull request Jun 12, 2026
Summary:
No functional change. Restructures ParamList:fmt_with_type to first compute what it needs to write, then write everything in a block at the end. This will make the next diff easier to read.

Context:

This stack is a ground-up re-implementation of #1447. It has a narrower focus (just omits irrelevant parameter types, doesn't try to do any handling of other kinds of call errors), reuses the existing signature display code, tracks parameters by name instead of index, and filters all overload signatures rather than just the closest one.

Reviewed By: yangdanny97

Differential Revision: D108230392

fbshipit-source-id: 980152f39bc882f57ab8670308dad64bf4be6e93
meta-codesync Bot pushed a commit that referenced this pull request Jun 12, 2026
Summary:
Adds a `ParamOverlay` enum to control which parameters are included when displaying a ParamsList. The enum has two variants: `All` (include all params) and `Subset(SmallSet<Name>)` (include only this set of params). Anonymous params (name=None) are always included. Params that are not included are replaced with `...`. `/` and `*` markers are always included.

This will be used in the next diff to improve signature display in no-matching-overload errors.

Context:

This stack is a ground-up re-implementation of #1447. It has a narrower focus (just omits irrelevant parameter types, doesn't try to do any handling of other kinds of call errors), reuses the existing signature display code, tracks parameters by name instead of index, and filters all overload signatures rather than just the closest one.

Reviewed By: grievejia

Differential Revision: D108230385

fbshipit-source-id: 50a4425640cdd31caf8bfc644f07d3cab7fc6545
meta-codesync Bot pushed a commit that referenced this pull request Jun 12, 2026
Summary:
Stores required parameters that were not matched by any arguments in ArgMap. This will be used to improve no-matching-overload error messages.

Context:

This stack is a ground-up re-implementation of #1447. It has a narrower focus (just omits irrelevant parameter types, doesn't try to do any handling of other kinds of call errors), reuses the existing signature display code, tracks parameters by name instead of index, and filters all overload signatures rather than just the closest one.

Reviewed By: yangdanny97

Differential Revision: D108250102

fbshipit-source-id: a6ef981f46cfad0b2dc1af19c50447e132d93913
meta-codesync Bot pushed a commit that referenced this pull request Jun 12, 2026
Summary:
When a call to an overloaded function fails but has the right number of arguments, show only the parameters corresponding to passed arguments and required missing arguments when printing possible overloads. This makes the signatures easier to read by hiding irrelevant information.

Before:
```
ERROR No matching overload found for function `subprocess.run` called with arguments: (Literal[42], capture_output=Any) [no-matching-overload]
 --> empty.py:6:15
  |
6 | subprocess.run(42, capture_output=x)
  |               ^^^^^^^^^^^^^^^^^^^^^^
  |
  Possible overloads:
    (args: _CMD, bufsize: int = -1, executable: PathLike[bytes] | PathLike[str] | bytes | str | None = None, stdin: _FILE = None, stdout: _FILE = None, stderr: _FILE = None, preexec_fn: (() -> object) | None = None, close_fds: bool = True, shell: bool = False, cwd: PathLike[bytes] | PathLike[str] | bytes | str | None = None, env: Mapping[bytes, StrOrBytesPath] | Mapping[str, StrOrBytesPath] | None = None, universal_newlines: Literal[True] | None = None, startupinfo: Any = None, creationflags: int = 0, restore_signals: bool = True, start_new_session: bool = False, pass_fds: Collection[int] = ..., *, capture_output: bool = False, check: bool = False, encoding: str | None = None, errors: str | None = None, input: str | None = None, text: Literal[True], timeout: float | None = None, user: int | str | None = None, group: int | str | None = None, extra_groups: Iterable[int | str] | None = None, umask: int = -1, pipesize: int = -1, process_group: int | None = None) -> CompletedProcess[str]
    (args: _CMD, bufsize: int = -1, executable: PathLike[bytes] | PathLike[str] | bytes | str | None = None, stdin: _FILE = None, stdout: _FILE = None, stderr: _FILE = None, preexec_fn: (() -> object) | None = None, close_fds: bool = True, shell: bool = False, cwd: PathLike[bytes] | PathLike[str] | bytes | str | None = None, env: Mapping[bytes, StrOrBytesPath] | Mapping[str, StrOrBytesPath] | None = None, universal_newlines: bool | None = None, startupinfo: Any = None, creationflags: int = 0, restore_signals: bool = True, start_new_session: bool = False, pass_fds: Collection[int] = ..., *, capture_output: bool = False, check: bool = False, encoding: str, errors: str | None = None, input: str | None = None, text: bool | None = None, timeout: float | None = None, user: int | str | None = None, group: int | str | None = None, extra_groups: Iterable[int | str] | None = None, umask: int = -1, pipesize: int = -1, process_group: int | None = None) -> CompletedProcess[str]
    (args: _CMD, bufsize: int = -1, executable: PathLike[bytes] | PathLike[str] | bytes | str | None = None, stdin: _FILE = None, stdout: _FILE = None, stderr: _FILE = None, preexec_fn: (() -> object) | None = None, close_fds: bool = True, shell: bool = False, cwd: PathLike[bytes] | PathLike[str] | bytes | str | None = None, env: Mapping[bytes, StrOrBytesPath] | Mapping[str, StrOrBytesPath] | None = None, universal_newlines: bool | None = None, startupinfo: Any = None, creationflags: int = 0, restore_signals: bool = True, start_new_session: bool = False, pass_fds: Collection[int] = ..., *, capture_output: bool = False, check: bool = False, encoding: str | None = None, errors: str, input: str | None = None, text: bool | None = None, timeout: float | None = None, user: int | str | None = None, group: int | str | None = None, extra_groups: Iterable[int | str] | None = None, umask: int = -1, pipesize: int = -1, process_group: int | None = None) -> CompletedProcess[str]
    (args: _CMD, bufsize: int = -1, executable: PathLike[bytes] | PathLike[str] | bytes | str | None = None, stdin: _FILE = None, stdout: _FILE = None, stderr: _FILE = None, preexec_fn: (() -> object) | None = None, close_fds: bool = True, shell: bool = False, cwd: PathLike[bytes] | PathLike[str] | bytes | str | None = None, env: Mapping[bytes, StrOrBytesPath] | Mapping[str, StrOrBytesPath] | None = None, *, universal_newlines: Literal[True], startupinfo: Any = None, creationflags: int = 0, restore_signals: bool = True, start_new_session: bool = False, pass_fds: Collection[int] = ..., capture_output: bool = False, check: bool = False, encoding: str | None = None, errors: str | None = None, input: str | None = None, text: Literal[True] | None = None, timeout: float | None = None, user: int | str | None = None, group: int | str | None = None, extra_groups: Iterable[int | str] | None = None, umask: int = -1, pipesize: int = -1, process_group: int | None = None) -> CompletedProcess[str]
    (args: _CMD, bufsize: int = -1, executable: PathLike[bytes] | PathLike[str] | bytes | str | None = None, stdin: _FILE = None, stdout: _FILE = None, stderr: _FILE = None, preexec_fn: (() -> object) | None = None, close_fds: bool = True, shell: bool = False, cwd: PathLike[bytes] | PathLike[str] | bytes | str | None = None, env: Mapping[bytes, StrOrBytesPath] | Mapping[str, StrOrBytesPath] | None = None, universal_newlines: Literal[False] | None = None, startupinfo: Any = None, creationflags: int = 0, restore_signals: bool = True, start_new_session: bool = False, pass_fds: Collection[int] = ..., *, capture_output: bool = False, check: bool = False, encoding: None = None, errors: None = None, input: Buffer | None = None, text: Literal[False] | None = None, timeout: float | None = None, user: int | str | None = None, group: int | str | None = None, extra_groups: Iterable[int | str] | None = None, umask: int = -1, pipesize: int = -1, process_group: int | None = None) -> CompletedProcess[bytes] [closest match]
    (args: _CMD, bufsize: int = -1, executable: PathLike[bytes] | PathLike[str] | bytes | str | None = None, stdin: _FILE = None, stdout: _FILE = None, stderr: _FILE = None, preexec_fn: (() -> object) | None = None, close_fds: bool = True, shell: bool = False, cwd: PathLike[bytes] | PathLike[str] | bytes | str | None = None, env: Mapping[bytes, StrOrBytesPath] | Mapping[str, StrOrBytesPath] | None = None, universal_newlines: bool | None = None, startupinfo: Any = None, creationflags: int = 0, restore_signals: bool = True, start_new_session: bool = False, pass_fds: Collection[int] = ..., *, capture_output: bool = False, check: bool = False, encoding: str | None = None, errors: str | None = None, input: Buffer | str | None = None, text: bool | None = None, timeout: float | None = None, user: int | str | None = None, group: int | str | None = None, extra_groups: Iterable[int | str] | None = None, umask: int = -1, pipesize: int = -1, process_group: int | None = None) -> CompletedProcess[Any]
  Argument `Literal[42]` is not assignable to parameter `args` with type `PathLike[bytes] | PathLike[str] | Sequence[StrOrBytesPath] | bytes | str` in function `subprocess.run`
```

After:
```
ERROR No matching overload found for function `subprocess.run` called with arguments: (Literal[42], capture_output=Any) [no-matching-overload]
 --> empty.py:6:15
  |
6 | subprocess.run(42, capture_output=x)
  |               ^^^^^^^^^^^^^^^^^^^^^^
  |
  Possible overloads:
    (args: _CMD, ..., *, capture_output: bool = False, ...) -> CompletedProcess[str]
    (args: _CMD, ..., *, capture_output: bool = False, ...) -> CompletedProcess[str]
    (args: _CMD, ..., *, capture_output: bool = False, ...) -> CompletedProcess[str]
    (args: _CMD, ..., *, ..., capture_output: bool = False, ...) -> CompletedProcess[str]
    (args: _CMD, ..., *, capture_output: bool = False, ...) -> CompletedProcess[bytes] [closest match]
    (args: _CMD, ..., *, capture_output: bool = False, ...) -> CompletedProcess[Any]
  Argument `Literal[42]` is not assignable to parameter `args` with type `PathLike[bytes] | PathLike[str] | Sequence[StrOrBytesPath] | bytes | str` in function `subprocess.run`
```

Closes #955. There are two requests in that issue (hide unrelated fields, add line breaks). I don't think we should do the second, because it would make no-matching-overload errors very long, so this completes the actionable part.

Context:

This stack is a ground-up re-implementation of #1447. It has a narrower focus (just omits irrelevant parameter types, doesn't try to do any handling of other kinds of call errors), reuses the existing signature display code, tracks parameters by name instead of index, and filters all overload signatures rather than just the closest one.

Reviewed By: samwgoldman

Differential Revision: D108230384

fbshipit-source-id: 1a29b445d7daccf703fa64927416f2b425bd1f89
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.

5 participants