diff --git a/crates/ty_python_semantic/resources/mdtest/call/builtins.md b/crates/ty_python_semantic/resources/mdtest/call/builtins.md index 742d275e3ddaa..bac85f49d6638 100644 --- a/crates/ty_python_semantic/resources/mdtest/call/builtins.md +++ b/crates/ty_python_semantic/resources/mdtest/call/builtins.md @@ -200,6 +200,9 @@ isinstance("", t.Any) # error: [invalid-argument-type] ## The builtin `NotImplemented` constant is not callable + + ```py -NotImplemented() # error: [call-non-callable] +raise NotImplemented() # error: [call-non-callable] +raise NotImplemented("this module is not implemented yet!!!") # error: [call-non-callable] ``` diff --git "a/crates/ty_python_semantic/resources/mdtest/snapshots/builtins.md_-_Calling_builtins_-_The_builtin_`NotImpl\342\200\246_(ac366391ebdec9c0).snap" "b/crates/ty_python_semantic/resources/mdtest/snapshots/builtins.md_-_Calling_builtins_-_The_builtin_`NotImpl\342\200\246_(ac366391ebdec9c0).snap" new file mode 100644 index 0000000000000..0e6ea4d5366a8 --- /dev/null +++ "b/crates/ty_python_semantic/resources/mdtest/snapshots/builtins.md_-_Calling_builtins_-_The_builtin_`NotImpl\342\200\246_(ac366391ebdec9c0).snap" @@ -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 + +``` diff --git a/crates/ty_python_semantic/src/types/infer/builder.rs b/crates/ty_python_semantic/src/types/infer/builder.rs index 85c645d37a529..3afbd10858e58 100644 --- a/crates/ty_python_semantic/src/types/infer/builder.rs +++ b/crates/ty_python_semantic/src/types/infer/builder.rs @@ -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);