Improve error messages when positional arguments are missing#20591
Improve error messages when positional arguments are missing#20591KevinRK29 wants to merge 12 commits intopython:masterfrom
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
1 similar comment
This comment has been minimized.
This comment has been minimized.
| f("hello", b'x') | ||
| [builtins fixtures/primitives.pyi] | ||
| [out] | ||
| main:3: error: Missing positional argument "z" in call to "f" |
There was a problem hiding this comment.
In this case it's not clear what the idea error message would be, since the caller accepts *args. One option would be to report missing positional argument x, but maybe it could result in confusing messages in other contexts, so these messages are reasonable. However, I think it would better to show the 'Missing positional argument ...' after the other messages, so that the messages could be shown in a logical order.
There was a problem hiding this comment.
So I did try this, however I noticed how the errors in mypy work is that it orders them based on column.
"Missing positional argument 'y'" is in column 1 and "Argument 1 has incompatible type" is in column 3. So the "Missing positional" error was always sorted first.
I tried making it so that the context/column for this error to be the last one, but that also affects Too few arguments for "x" since they're in the same code block and moves that to the bottom.
But also the other thing is that it changed the column at which this error occurs, so for
[case testColumnInvalidArguments]
(f()) # E:2: Missing positional arguments "x", "y" in call to "f"
(f(y=1)) # E:6: Missing positional argument "x" in call to "f"
It becomes E:6 instead of E:2, where I feel E:2 might be more correct since it's pointing to f?
Anyways that was what I was seeing, and I wanted more thoughts before committing the change on whether this is fine or not.
| f("hello") | ||
| [builtins fixtures/primitives.pyi] | ||
| [out] | ||
| main:3: error: Missing positional argument "y" in call to "f" |
There was a problem hiding this comment.
Can you report this error after the 'Argument N to ...' errors, so that we'd report the errors in the same order as the arguments are in the call.
| f(1.5, [1, 2, 3]) | ||
| [builtins fixtures/list.pyi] | ||
| [out] | ||
| main:3: error: Missing positional arguments "c", "d" in call to "f" |
There was a problem hiding this comment.
Since there are multiple positional arguments missing, it seems reasonable to not try to align them, so this looks fine, but it would be clearer if the order of the errors would be different (see my other comments).
This comment has been minimized.
This comment has been minimized.
3340653 to
9640b70
Compare
This comment has been minimized.
This comment has been minimized.
8697344 to
d1d525f
Compare
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
…clude implementation details
d1d525f to
c967cdb
Compare
for more information, see https://pre-commit.ci
This comment has been minimized.
This comment has been minimized.
JukkaL
left a comment
There was a problem hiding this comment.
Thanks for simplifying the PR! Now the main concern is the CPU cost of the new check. There seems to be a way to avoid almost all of the extra overhead, however.
mypy/checkexpr.py
Outdated
| object_type, | ||
| callable_name, | ||
| ) | ||
| if not self._detect_missing_positional_arg(callee, arg_types, arg_kinds, args, context): |
There was a problem hiding this comment.
Now the extra is triggered on every function call check, which is a hot code path. We should only do the extra checks when we already know the argument types don't match, and we will be reporting the error message, to avoid performance issues (this is a real concern -- we've had many performance regressions/bottlenecks due to expensive error reporting). Also if prefer_simple_messages() is true, we should skip the extra logic, similar to all other potentially expensive error message processing.
In summary, only once we know that we need to report a message about incompatible arguments, the new check can be used to potentially override the default generated error messages. The new error message only applies to a small fraction of all calls, so we should delay the check as much as possible.
This comment has been minimized.
This comment has been minimized.
3933fc9 to
1ff910c
Compare
This comment has been minimized.
This comment has been minimized.
|
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
Summary
This PR improves error messages when positional arguments are missing from a function call.
Previously when a user forgets a positional argument, mypy would previously emit multiple type errors because the subsequent arguments would be "shifted" and mismatched with their expected types. Instead of showing multiple type errors, it emits a single consolidated message that suggests which argument might be missing.