red_knot_python_semantic: migrate types/call/bind to new diagnostics

This commit is contained in:
Andrew Gallant 2025-04-22 09:26:37 -04:00 committed by Andrew Gallant
parent ad5a659f29
commit 3796b13ea2
2 changed files with 49 additions and 62 deletions

View file

@ -18,11 +18,11 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/diagnostics/no_mat
# Diagnostics # Diagnostics
``` ```
error: lint:no-matching-overload error: lint:no-matching-overload: No overload of class `type` matches arguments
--> /src/mdtest_snippet.py:1:1 --> /src/mdtest_snippet.py:1:1
| |
1 | type("Foo", ()) # error: [no-matching-overload] 1 | type("Foo", ()) # error: [no-matching-overload]
| ^^^^^^^^^^^^^^^ No overload of class `type` matches arguments | ^^^^^^^^^^^^^^^
| |
``` ```

View file

@ -179,24 +179,23 @@ impl<'db> Bindings<'db> {
// If all union elements are not callable, report that the union as a whole is not // If all union elements are not callable, report that the union as a whole is not
// callable. // callable.
if self.into_iter().all(|b| !b.is_callable()) { if self.into_iter().all(|b| !b.is_callable()) {
context.report_lint_old( if let Some(builder) = context.report_lint(&CALL_NON_CALLABLE, node) {
&CALL_NON_CALLABLE, builder.into_diagnostic(format_args!(
node,
format_args!(
"Object of type `{}` is not callable", "Object of type `{}` is not callable",
self.callable_type().display(context.db()) self.callable_type().display(context.db())
), ));
); }
return; return;
} }
for (index, conflicting_form) in self.conflicting_forms.iter().enumerate() { for (index, conflicting_form) in self.conflicting_forms.iter().enumerate() {
if *conflicting_form { if *conflicting_form {
context.report_lint_old( let node = BindingError::get_node(node, Some(index));
&CONFLICTING_ARGUMENT_FORMS, if let Some(builder) = context.report_lint(&CONFLICTING_ARGUMENT_FORMS, node) {
BindingError::get_node(node, Some(index)), builder.into_diagnostic(
format_args!("Argument is used as both a value and a type form in call"), "Argument is used as both a value and a type form in call",
); );
}
} }
} }
@ -907,43 +906,37 @@ impl<'db> CallableBinding<'db> {
fn report_diagnostics(&self, context: &InferContext<'db>, node: ast::AnyNodeRef) { fn report_diagnostics(&self, context: &InferContext<'db>, node: ast::AnyNodeRef) {
if !self.is_callable() { if !self.is_callable() {
context.report_lint_old( if let Some(builder) = context.report_lint(&CALL_NON_CALLABLE, node) {
&CALL_NON_CALLABLE, builder.into_diagnostic(format_args!(
node,
format_args!(
"Object of type `{}` is not callable", "Object of type `{}` is not callable",
self.callable_type.display(context.db()), self.callable_type.display(context.db()),
), ));
); }
return; return;
} }
if self.dunder_call_is_possibly_unbound { if self.dunder_call_is_possibly_unbound {
context.report_lint_old( if let Some(builder) = context.report_lint(&CALL_NON_CALLABLE, node) {
&CALL_NON_CALLABLE, builder.into_diagnostic(format_args!(
node,
format_args!(
"Object of type `{}` is not callable (possibly unbound `__call__` method)", "Object of type `{}` is not callable (possibly unbound `__call__` method)",
self.callable_type.display(context.db()), self.callable_type.display(context.db()),
), ));
); }
return; return;
} }
let callable_description = CallableDescription::new(context.db(), self.callable_type); let callable_description = CallableDescription::new(context.db(), self.callable_type);
if self.overloads.len() > 1 { if self.overloads.len() > 1 {
context.report_lint_old( if let Some(builder) = context.report_lint(&NO_MATCHING_OVERLOAD, node) {
&NO_MATCHING_OVERLOAD, builder.into_diagnostic(format_args!(
node,
format_args!(
"No overload{} matches arguments", "No overload{} matches arguments",
if let Some(CallableDescription { kind, name }) = callable_description { if let Some(CallableDescription { kind, name }) = callable_description {
format!(" of {kind} `{name}`") format!(" of {kind} `{name}`")
} else { } else {
String::new() String::new()
} }
), ));
); }
return; return;
} }
@ -1444,10 +1437,9 @@ impl<'db> BindingError<'db> {
expected_positional_count, expected_positional_count,
provided_positional_count, provided_positional_count,
} => { } => {
context.report_lint_old( let node = Self::get_node(node, *first_excess_argument_index);
&TOO_MANY_POSITIONAL_ARGUMENTS, if let Some(builder) = context.report_lint(&TOO_MANY_POSITIONAL_ARGUMENTS, node) {
Self::get_node(node, *first_excess_argument_index), builder.into_diagnostic(format_args!(
format_args!(
"Too many positional arguments{}: expected \ "Too many positional arguments{}: expected \
{expected_positional_count}, got {provided_positional_count}", {expected_positional_count}, got {provided_positional_count}",
if let Some(CallableDescription { kind, name }) = callable_description { if let Some(CallableDescription { kind, name }) = callable_description {
@ -1455,75 +1447,70 @@ impl<'db> BindingError<'db> {
} else { } else {
String::new() String::new()
} }
), ));
); }
} }
Self::MissingArguments { parameters } => { Self::MissingArguments { parameters } => {
let s = if parameters.0.len() == 1 { "" } else { "s" }; if let Some(builder) = context.report_lint(&MISSING_ARGUMENT, node) {
context.report_lint_old( let s = if parameters.0.len() == 1 { "" } else { "s" };
&MISSING_ARGUMENT, builder.into_diagnostic(format_args!(
node,
format_args!(
"No argument{s} provided for required parameter{s} {parameters}{}", "No argument{s} provided for required parameter{s} {parameters}{}",
if let Some(CallableDescription { kind, name }) = callable_description { if let Some(CallableDescription { kind, name }) = callable_description {
format!(" of {kind} `{name}`") format!(" of {kind} `{name}`")
} else { } else {
String::new() String::new()
} }
), ));
); }
} }
Self::UnknownArgument { Self::UnknownArgument {
argument_name, argument_name,
argument_index, argument_index,
} => { } => {
context.report_lint_old( let node = Self::get_node(node, *argument_index);
&UNKNOWN_ARGUMENT, if let Some(builder) = context.report_lint(&UNKNOWN_ARGUMENT, node) {
Self::get_node(node, *argument_index), builder.into_diagnostic(format_args!(
format_args!(
"Argument `{argument_name}` does not match any known parameter{}", "Argument `{argument_name}` does not match any known parameter{}",
if let Some(CallableDescription { kind, name }) = callable_description { if let Some(CallableDescription { kind, name }) = callable_description {
format!(" of {kind} `{name}`") format!(" of {kind} `{name}`")
} else { } else {
String::new() String::new()
} }
), ));
); }
} }
Self::ParameterAlreadyAssigned { Self::ParameterAlreadyAssigned {
argument_index, argument_index,
parameter, parameter,
} => { } => {
context.report_lint_old( let node = Self::get_node(node, *argument_index);
&PARAMETER_ALREADY_ASSIGNED, if let Some(builder) = context.report_lint(&PARAMETER_ALREADY_ASSIGNED, node) {
Self::get_node(node, *argument_index), builder.into_diagnostic(format_args!(
format_args!(
"Multiple values provided for parameter {parameter}{}", "Multiple values provided for parameter {parameter}{}",
if let Some(CallableDescription { kind, name }) = callable_description { if let Some(CallableDescription { kind, name }) = callable_description {
format!(" of {kind} `{name}`") format!(" of {kind} `{name}`")
} else { } else {
String::new() String::new()
} }
), ));
); }
} }
Self::InternalCallError(reason) => { Self::InternalCallError(reason) => {
context.report_lint_old( let node = Self::get_node(node, None);
&CALL_NON_CALLABLE, if let Some(builder) = context.report_lint(&CALL_NON_CALLABLE, node) {
Self::get_node(node, None), builder.into_diagnostic(format_args!(
format_args!(
"Call{} failed: {reason}", "Call{} failed: {reason}",
if let Some(CallableDescription { kind, name }) = callable_description { if let Some(CallableDescription { kind, name }) = callable_description {
format!(" of {kind} `{name}`") format!(" of {kind} `{name}`")
} else { } else {
String::new() String::new()
} }
), ));
); }
} }
} }
} }