[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:
Alex Waygood
2025-11-19 19:27:12 +00:00
committed by GitHub
parent ce06094ada
commit a8f7ccf2ca
3 changed files with 69 additions and 1 deletions

View File

@@ -200,6 +200,9 @@ isinstance("", t.Any) # error: [invalid-argument-type]
## The builtin `NotImplemented` constant is not callable
<!-- snapshot-diagnostics -->
```py
NotImplemented() # error: [call-non-callable]
raise NotImplemented() # error: [call-non-callable]
raise NotImplemented("this module is not implemented yet!!!") # error: [call-non-callable]
```

View File

@@ -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
```