[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

@@ -7912,6 +7912,24 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
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
if let ast::Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = func.as_ref() {
let value_type = self.expression_type(value);