mirror of https://github.com/astral-sh/ruff
[ty] Improve diagnostics when `NotImplemented` is called (#21523)
## Summary Fixes https://github.com/astral-sh/ty/issues/1571. I realised I was overcomplicating things when I described what we should do in that issue description. The simplest thing to do here is just to special-case call expressions and short-circuit the call-binding machinery entirely if we see it's `NotImplemented` being called. It doesn't really matter if the subdiagnostic doesn't fire when a union is called and one element of the union is `NotImplemented` -- the subdiagnostic doesn't need to be exhaustive; it's just to help people in some common cases. ## Test Plan Added snapshots
This commit is contained in:
parent
ce06094ada
commit
a8f7ccf2ca
|
|
@ -200,6 +200,9 @@ isinstance("", t.Any) # error: [invalid-argument-type]
|
||||||
|
|
||||||
## The builtin `NotImplemented` constant is not callable
|
## The builtin `NotImplemented` constant is not callable
|
||||||
|
|
||||||
|
<!-- snapshot-diagnostics -->
|
||||||
|
|
||||||
```py
|
```py
|
||||||
NotImplemented() # error: [call-non-callable]
|
raise NotImplemented() # error: [call-non-callable]
|
||||||
|
raise NotImplemented("this module is not implemented yet!!!") # error: [call-non-callable]
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
---
|
||||||
|
source: crates/ty_test/src/lib.rs
|
||||||
|
expression: snapshot
|
||||||
|
---
|
||||||
|
---
|
||||||
|
mdtest name: builtins.md - Calling builtins - The builtin `NotImplemented` constant is not callable
|
||||||
|
mdtest path: crates/ty_python_semantic/resources/mdtest/call/builtins.md
|
||||||
|
---
|
||||||
|
|
||||||
|
# Python source files
|
||||||
|
|
||||||
|
## mdtest_snippet.py
|
||||||
|
|
||||||
|
```
|
||||||
|
1 | raise NotImplemented() # error: [call-non-callable]
|
||||||
|
2 | raise NotImplemented("this module is not implemented yet!!!") # error: [call-non-callable]
|
||||||
|
```
|
||||||
|
|
||||||
|
# Diagnostics
|
||||||
|
|
||||||
|
```
|
||||||
|
error[call-non-callable]: `NotImplemented` is not callable
|
||||||
|
--> src/mdtest_snippet.py:1:7
|
||||||
|
|
|
||||||
|
1 | raise NotImplemented() # error: [call-non-callable]
|
||||||
|
| --------------^^
|
||||||
|
| |
|
||||||
|
| Did you mean `NotImplementedError`?
|
||||||
|
2 | raise NotImplemented("this module is not implemented yet!!!") # error: [call-non-callable]
|
||||||
|
|
|
||||||
|
info: rule `call-non-callable` is enabled by default
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
error[call-non-callable]: `NotImplemented` is not callable
|
||||||
|
--> src/mdtest_snippet.py:2:7
|
||||||
|
|
|
||||||
|
1 | raise NotImplemented() # error: [call-non-callable]
|
||||||
|
2 | raise NotImplemented("this module is not implemented yet!!!") # error: [call-non-callable]
|
||||||
|
| --------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| Did you mean `NotImplementedError`?
|
||||||
|
|
|
||||||
|
info: rule `call-non-callable` is enabled by default
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -7912,6 +7912,24 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
ty
|
ty
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if callable_type.is_notimplemented(self.db()) {
|
||||||
|
if let Some(builder) = self
|
||||||
|
.context
|
||||||
|
.report_lint(&CALL_NON_CALLABLE, call_expression)
|
||||||
|
{
|
||||||
|
let mut diagnostic = builder.into_diagnostic("`NotImplemented` is not callable");
|
||||||
|
diagnostic.annotate(
|
||||||
|
self.context
|
||||||
|
.secondary(&**func)
|
||||||
|
.message("Did you mean `NotImplementedError`?"),
|
||||||
|
);
|
||||||
|
diagnostic.set_concise_message(
|
||||||
|
"`NotImplemented` is not callable - did you mean `NotImplementedError`?",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Type::unknown();
|
||||||
|
}
|
||||||
|
|
||||||
// Special handling for `TypedDict` method calls
|
// Special handling for `TypedDict` method calls
|
||||||
if let ast::Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = func.as_ref() {
|
if let ast::Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = func.as_ref() {
|
||||||
let value_type = self.expression_type(value);
|
let value_type = self.expression_type(value);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue