mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 13:24:57 +00:00
[ty] Rename "possibly unbound" diagnostics to "possibly missing" (#20492)
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
This commit is contained in:
parent
4ed8c65d29
commit
bf38e69870
41 changed files with 213 additions and 194 deletions
|
@ -8,7 +8,7 @@ use bitflags::bitflags;
|
|||
use call::{CallDunderError, CallError, CallErrorKind};
|
||||
use context::InferContext;
|
||||
use diagnostic::{
|
||||
INVALID_CONTEXT_MANAGER, INVALID_SUPER_ARGUMENT, NOT_ITERABLE, POSSIBLY_UNBOUND_IMPLICIT_CALL,
|
||||
INVALID_CONTEXT_MANAGER, INVALID_SUPER_ARGUMENT, NOT_ITERABLE, POSSIBLY_MISSING_IMPLICIT_CALL,
|
||||
UNAVAILABLE_IMPLICIT_SUPER_ARGUMENTS,
|
||||
};
|
||||
use ruff_db::diagnostic::{Annotation, Diagnostic, Span, SubDiagnostic, SubDiagnosticSeverity};
|
||||
|
@ -3830,7 +3830,7 @@ impl<'db> Type<'db> {
|
|||
});
|
||||
}
|
||||
|
||||
// Don't trust possibly unbound `__bool__` method.
|
||||
// Don't trust possibly missing `__bool__` method.
|
||||
Ok(Truthiness::Ambiguous)
|
||||
}
|
||||
|
||||
|
@ -8148,7 +8148,7 @@ impl<'db> AwaitError<'db> {
|
|||
}
|
||||
}
|
||||
Self::Call(CallDunderError::PossiblyUnbound(bindings)) => {
|
||||
diag.info("`__await__` is possibly unbound");
|
||||
diag.info("`__await__` may be missing");
|
||||
if let Some(definition_spans) = bindings.callable_type().function_spans(db) {
|
||||
diag.annotate(
|
||||
Annotation::secondary(definition_spans.signature)
|
||||
|
@ -8255,7 +8255,7 @@ impl<'db> ContextManagerError<'db> {
|
|||
match call_dunder_error {
|
||||
CallDunderError::MethodNotAvailable => format!("it does not implement `{name}`"),
|
||||
CallDunderError::PossiblyUnbound(_) => {
|
||||
format!("the method `{name}` is possibly unbound")
|
||||
format!("the method `{name}` may be missing")
|
||||
}
|
||||
// TODO: Use more specific error messages for the different error cases.
|
||||
// E.g. hint toward the union variant that doesn't correctly implement enter,
|
||||
|
@ -8272,7 +8272,7 @@ impl<'db> ContextManagerError<'db> {
|
|||
name_b: &str| {
|
||||
match (error_a, error_b) {
|
||||
(CallDunderError::PossiblyUnbound(_), CallDunderError::PossiblyUnbound(_)) => {
|
||||
format!("the methods `{name_a}` and `{name_b}` are possibly unbound")
|
||||
format!("the methods `{name_a}` and `{name_b}` are possibly missing")
|
||||
}
|
||||
(CallDunderError::MethodNotAvailable, CallDunderError::MethodNotAvailable) => {
|
||||
format!("it does not implement `{name_a}` and `{name_b}`")
|
||||
|
@ -8821,7 +8821,7 @@ pub(super) enum BoolError<'db> {
|
|||
|
||||
/// Any other reason why the type can't be converted to a bool.
|
||||
/// E.g. because calling `__bool__` returns in a union type and not all variants support `__bool__` or
|
||||
/// because `__bool__` points to a type that has a possibly unbound `__call__` method.
|
||||
/// because `__bool__` points to a type that has a possibly missing `__call__` method.
|
||||
Other { not_boolable_type: Type<'db> },
|
||||
}
|
||||
|
||||
|
@ -8994,7 +8994,7 @@ impl<'db> ConstructorCallError<'db> {
|
|||
let report_init_error = |call_dunder_error: &CallDunderError<'db>| match call_dunder_error {
|
||||
CallDunderError::MethodNotAvailable => {
|
||||
if let Some(builder) =
|
||||
context.report_lint(&POSSIBLY_UNBOUND_IMPLICIT_CALL, context_expression_node)
|
||||
context.report_lint(&POSSIBLY_MISSING_IMPLICIT_CALL, context_expression_node)
|
||||
{
|
||||
// If we are using vendored typeshed, it should be impossible to have missing
|
||||
// or unbound `__init__` method on a class, as all classes have `object` in MRO.
|
||||
|
@ -9008,10 +9008,10 @@ impl<'db> ConstructorCallError<'db> {
|
|||
}
|
||||
CallDunderError::PossiblyUnbound(bindings) => {
|
||||
if let Some(builder) =
|
||||
context.report_lint(&POSSIBLY_UNBOUND_IMPLICIT_CALL, context_expression_node)
|
||||
context.report_lint(&POSSIBLY_MISSING_IMPLICIT_CALL, context_expression_node)
|
||||
{
|
||||
builder.into_diagnostic(format_args!(
|
||||
"Method `__init__` on type `{}` is possibly unbound.",
|
||||
"Method `__init__` on type `{}` may be missing.",
|
||||
context_expression_type.display(context.db()),
|
||||
));
|
||||
}
|
||||
|
@ -9026,10 +9026,10 @@ impl<'db> ConstructorCallError<'db> {
|
|||
let report_new_error = |error: &DunderNewCallError<'db>| match error {
|
||||
DunderNewCallError::PossiblyUnbound(call_error) => {
|
||||
if let Some(builder) =
|
||||
context.report_lint(&POSSIBLY_UNBOUND_IMPLICIT_CALL, context_expression_node)
|
||||
context.report_lint(&POSSIBLY_MISSING_IMPLICIT_CALL, context_expression_node)
|
||||
{
|
||||
builder.into_diagnostic(format_args!(
|
||||
"Method `__new__` on type `{}` is possibly unbound.",
|
||||
"Method `__new__` on type `{}` may be missing.",
|
||||
context_expression_type.display(context.db()),
|
||||
));
|
||||
}
|
||||
|
|
|
@ -1758,7 +1758,7 @@ impl<'db> CallableBinding<'db> {
|
|||
if self.dunder_call_is_possibly_unbound {
|
||||
if let Some(builder) = context.report_lint(&CALL_NON_CALLABLE, node) {
|
||||
let mut diag = builder.into_diagnostic(format_args!(
|
||||
"Object of type `{}` is not callable (possibly unbound `__call__` method)",
|
||||
"Object of type `{}` is not callable (possibly missing `__call__` method)",
|
||||
self.callable_type.display(context.db()),
|
||||
));
|
||||
if let Some(union_diag) = union_diag {
|
||||
|
|
|
@ -38,7 +38,7 @@ use std::fmt::Formatter;
|
|||
pub(crate) fn register_lints(registry: &mut LintRegistryBuilder) {
|
||||
registry.register_lint(&AMBIGUOUS_PROTOCOL_MEMBER);
|
||||
registry.register_lint(&CALL_NON_CALLABLE);
|
||||
registry.register_lint(&POSSIBLY_UNBOUND_IMPLICIT_CALL);
|
||||
registry.register_lint(&POSSIBLY_MISSING_IMPLICIT_CALL);
|
||||
registry.register_lint(&CONFLICTING_ARGUMENT_FORMS);
|
||||
registry.register_lint(&CONFLICTING_DECLARATIONS);
|
||||
registry.register_lint(&CONFLICTING_METACLASS);
|
||||
|
@ -80,8 +80,8 @@ pub(crate) fn register_lints(registry: &mut LintRegistryBuilder) {
|
|||
registry.register_lint(&NOT_ITERABLE);
|
||||
registry.register_lint(&UNSUPPORTED_BOOL_CONVERSION);
|
||||
registry.register_lint(&PARAMETER_ALREADY_ASSIGNED);
|
||||
registry.register_lint(&POSSIBLY_UNBOUND_ATTRIBUTE);
|
||||
registry.register_lint(&POSSIBLY_UNBOUND_IMPORT);
|
||||
registry.register_lint(&POSSIBLY_MISSING_ATTRIBUTE);
|
||||
registry.register_lint(&POSSIBLY_MISSING_IMPORT);
|
||||
registry.register_lint(&POSSIBLY_UNRESOLVED_REFERENCE);
|
||||
registry.register_lint(&SUBCLASS_OF_FINAL_CLASS);
|
||||
registry.register_lint(&TYPE_ASSERTION_FAILURE);
|
||||
|
@ -131,12 +131,12 @@ declare_lint! {
|
|||
|
||||
declare_lint! {
|
||||
/// ## What it does
|
||||
/// Checks for implicit calls to possibly unbound methods.
|
||||
/// Checks for implicit calls to possibly missing methods.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Expressions such as `x[y]` and `x * y` call methods
|
||||
/// under the hood (`__getitem__` and `__mul__` respectively).
|
||||
/// Calling an unbound method will raise an `AttributeError` at runtime.
|
||||
/// Calling a missing method will raise an `AttributeError` at runtime.
|
||||
///
|
||||
/// ## Examples
|
||||
/// ```python
|
||||
|
@ -148,8 +148,8 @@ declare_lint! {
|
|||
///
|
||||
/// A()[0] # TypeError: 'A' object is not subscriptable
|
||||
/// ```
|
||||
pub(crate) static POSSIBLY_UNBOUND_IMPLICIT_CALL = {
|
||||
summary: "detects implicit calls to possibly unbound methods",
|
||||
pub(crate) static POSSIBLY_MISSING_IMPLICIT_CALL = {
|
||||
summary: "detects implicit calls to possibly missing methods",
|
||||
status: LintStatus::preview("1.0.0"),
|
||||
default_level: Level::Warn,
|
||||
}
|
||||
|
@ -1327,10 +1327,10 @@ declare_lint! {
|
|||
|
||||
declare_lint! {
|
||||
/// ## What it does
|
||||
/// Checks for possibly unbound attributes.
|
||||
/// Checks for possibly missing attributes.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Attempting to access an unbound attribute will raise an `AttributeError` at runtime.
|
||||
/// Attempting to access a missing attribute will raise an `AttributeError` at runtime.
|
||||
///
|
||||
/// ## Examples
|
||||
/// ```python
|
||||
|
@ -1340,8 +1340,8 @@ declare_lint! {
|
|||
///
|
||||
/// A.c # AttributeError: type object 'A' has no attribute 'c'
|
||||
/// ```
|
||||
pub(crate) static POSSIBLY_UNBOUND_ATTRIBUTE = {
|
||||
summary: "detects references to possibly unbound attributes",
|
||||
pub(crate) static POSSIBLY_MISSING_ATTRIBUTE = {
|
||||
summary: "detects references to possibly missing attributes",
|
||||
status: LintStatus::preview("1.0.0"),
|
||||
default_level: Level::Warn,
|
||||
}
|
||||
|
@ -1349,10 +1349,10 @@ declare_lint! {
|
|||
|
||||
declare_lint! {
|
||||
/// ## What it does
|
||||
/// Checks for imports of symbols that may be unbound.
|
||||
/// Checks for imports of symbols that may be missing.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Importing an unbound module or name will raise a `ModuleNotFoundError`
|
||||
/// Importing a missing module or name will raise a `ModuleNotFoundError`
|
||||
/// or `ImportError` at runtime.
|
||||
///
|
||||
/// ## Examples
|
||||
|
@ -1366,8 +1366,8 @@ declare_lint! {
|
|||
/// # main.py
|
||||
/// from module import a # ImportError: cannot import name 'a' from 'module'
|
||||
/// ```
|
||||
pub(crate) static POSSIBLY_UNBOUND_IMPORT = {
|
||||
summary: "detects possibly unbound imports",
|
||||
pub(crate) static POSSIBLY_MISSING_IMPORT = {
|
||||
summary: "detects possibly missing imports",
|
||||
status: LintStatus::preview("1.0.0"),
|
||||
default_level: Level::Warn,
|
||||
}
|
||||
|
@ -2197,17 +2197,17 @@ pub(super) fn report_possibly_unresolved_reference(
|
|||
builder.into_diagnostic(format_args!("Name `{id}` used when possibly not defined"));
|
||||
}
|
||||
|
||||
pub(super) fn report_possibly_unbound_attribute(
|
||||
pub(super) fn report_possibly_missing_attribute(
|
||||
context: &InferContext,
|
||||
target: &ast::ExprAttribute,
|
||||
attribute: &str,
|
||||
object_ty: Type,
|
||||
) {
|
||||
let Some(builder) = context.report_lint(&POSSIBLY_UNBOUND_ATTRIBUTE, target) else {
|
||||
let Some(builder) = context.report_lint(&POSSIBLY_MISSING_ATTRIBUTE, target) else {
|
||||
return;
|
||||
};
|
||||
builder.into_diagnostic(format_args!(
|
||||
"Attribute `{attribute}` on type `{}` is possibly unbound",
|
||||
"Attribute `{attribute}` on type `{}` may be missing",
|
||||
object_ty.display(context.db()),
|
||||
));
|
||||
}
|
||||
|
@ -2793,7 +2793,7 @@ pub(crate) fn report_invalid_or_unsupported_base(
|
|||
CallDunderError::PossiblyUnbound(_) => {
|
||||
explain_mro_entries(&mut diagnostic);
|
||||
diagnostic.info(format_args!(
|
||||
"Type `{}` has an `__mro_entries__` attribute, but it is possibly unbound",
|
||||
"Type `{}` may have an `__mro_entries__` attribute, but it may be missing",
|
||||
base_type.display(db)
|
||||
));
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ use crate::types::diagnostic::{
|
|||
INVALID_ASSIGNMENT, INVALID_ATTRIBUTE_ACCESS, INVALID_BASE, INVALID_DECLARATION,
|
||||
INVALID_GENERIC_CLASS, INVALID_KEY, INVALID_NAMED_TUPLE, INVALID_PARAMETER_DEFAULT,
|
||||
INVALID_TYPE_FORM, INVALID_TYPE_GUARD_CALL, INVALID_TYPE_VARIABLE_CONSTRAINTS,
|
||||
IncompatibleBases, NON_SUBSCRIPTABLE, POSSIBLY_UNBOUND_IMPLICIT_CALL, POSSIBLY_UNBOUND_IMPORT,
|
||||
IncompatibleBases, NON_SUBSCRIPTABLE, POSSIBLY_MISSING_IMPLICIT_CALL, POSSIBLY_MISSING_IMPORT,
|
||||
UNDEFINED_REVEAL, UNRESOLVED_ATTRIBUTE, UNRESOLVED_GLOBAL, UNRESOLVED_IMPORT,
|
||||
UNRESOLVED_REFERENCE, UNSUPPORTED_OPERATOR, report_bad_dunder_set_call,
|
||||
report_cannot_pop_required_field_on_typed_dict, report_implicit_return_type,
|
||||
|
@ -60,7 +60,7 @@ use crate::types::diagnostic::{
|
|||
report_invalid_attribute_assignment, report_invalid_generator_function_return_type,
|
||||
report_invalid_key_on_typed_dict, report_invalid_return_type,
|
||||
report_namedtuple_field_without_default_after_field_with_default,
|
||||
report_possibly_unbound_attribute,
|
||||
report_possibly_missing_attribute,
|
||||
};
|
||||
use crate::types::diagnostic::{
|
||||
INVALID_METACLASS, INVALID_OVERLOAD, INVALID_PROTOCOL, SUBCLASS_OF_FINAL_CLASS,
|
||||
|
@ -3222,10 +3222,10 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
Err(err) => match err {
|
||||
CallDunderError::PossiblyUnbound { .. } => {
|
||||
if let Some(builder) =
|
||||
context.report_lint(&POSSIBLY_UNBOUND_IMPLICIT_CALL, &**value)
|
||||
context.report_lint(&POSSIBLY_MISSING_IMPLICIT_CALL, &**value)
|
||||
{
|
||||
builder.into_diagnostic(format_args!(
|
||||
"Method `__setitem__` of type `{}` is possibly unbound",
|
||||
"Method `__setitem__` of type `{}` may be missing",
|
||||
value_ty.display(db),
|
||||
));
|
||||
}
|
||||
|
@ -3306,7 +3306,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
if let Some(builder) = context.report_lint(&CALL_NON_CALLABLE, &**value)
|
||||
{
|
||||
builder.into_diagnostic(format_args!(
|
||||
"Method `__setitem__` of type `{}` is possibly not \
|
||||
"Method `__setitem__` of type `{}` may not be \
|
||||
callable on object of type `{}`",
|
||||
bindings.callable_type().display(db),
|
||||
value_ty.display(db),
|
||||
|
@ -3642,7 +3642,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
};
|
||||
|
||||
if boundness == Boundness::PossiblyUnbound {
|
||||
report_possibly_unbound_attribute(
|
||||
report_possibly_missing_attribute(
|
||||
&self.context,
|
||||
target,
|
||||
attribute,
|
||||
|
@ -3672,7 +3672,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
}
|
||||
|
||||
if instance_attr_boundness == Boundness::PossiblyUnbound {
|
||||
report_possibly_unbound_attribute(
|
||||
report_possibly_missing_attribute(
|
||||
&self.context,
|
||||
target,
|
||||
attribute,
|
||||
|
@ -3752,7 +3752,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
};
|
||||
|
||||
if boundness == Boundness::PossiblyUnbound {
|
||||
report_possibly_unbound_attribute(
|
||||
report_possibly_missing_attribute(
|
||||
&self.context,
|
||||
target,
|
||||
attribute,
|
||||
|
@ -3783,7 +3783,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
}
|
||||
|
||||
if class_attr_boundness == Boundness::PossiblyUnbound {
|
||||
report_possibly_unbound_attribute(
|
||||
report_possibly_missing_attribute(
|
||||
&self.context,
|
||||
target,
|
||||
attribute,
|
||||
|
@ -4680,10 +4680,10 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
// together if the attribute exists but is possibly-unbound.
|
||||
if let Some(builder) = self
|
||||
.context
|
||||
.report_lint(&POSSIBLY_UNBOUND_IMPORT, AnyNodeRef::Alias(alias))
|
||||
.report_lint(&POSSIBLY_MISSING_IMPORT, AnyNodeRef::Alias(alias))
|
||||
{
|
||||
builder.into_diagnostic(format_args!(
|
||||
"Member `{name}` of module `{module_name}` is possibly unbound",
|
||||
"Member `{name}` of module `{module_name}` may be missing",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -6804,7 +6804,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
Type::unknown().into()
|
||||
}
|
||||
LookupError::PossiblyUnbound(type_when_bound) => {
|
||||
report_possibly_unbound_attribute(
|
||||
report_possibly_missing_attribute(
|
||||
&self.context,
|
||||
attribute,
|
||||
&attr.id,
|
||||
|
@ -8757,10 +8757,10 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
}
|
||||
Err(err @ CallDunderError::PossiblyUnbound { .. }) => {
|
||||
if let Some(builder) =
|
||||
context.report_lint(&POSSIBLY_UNBOUND_IMPLICIT_CALL, value_node)
|
||||
context.report_lint(&POSSIBLY_MISSING_IMPLICIT_CALL, value_node)
|
||||
{
|
||||
builder.into_diagnostic(format_args!(
|
||||
"Method `__getitem__` of type `{}` is possibly unbound",
|
||||
"Method `__getitem__` of type `{}` may be missing",
|
||||
value_ty.display(db),
|
||||
));
|
||||
}
|
||||
|
@ -8808,7 +8808,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
CallErrorKind::PossiblyNotCallable => {
|
||||
if let Some(builder) = context.report_lint(&CALL_NON_CALLABLE, value_node) {
|
||||
builder.into_diagnostic(format_args!(
|
||||
"Method `__getitem__` of type `{}` is possibly not callable on object of type `{}`",
|
||||
"Method `__getitem__` of type `{}` may not be callable on object of type `{}`",
|
||||
bindings.callable_type().display(db),
|
||||
value_ty.display(db),
|
||||
));
|
||||
|
@ -8840,11 +8840,10 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
Place::Type(ty, boundness) => {
|
||||
if boundness == Boundness::PossiblyUnbound {
|
||||
if let Some(builder) =
|
||||
context.report_lint(&POSSIBLY_UNBOUND_IMPLICIT_CALL, value_node)
|
||||
context.report_lint(&POSSIBLY_MISSING_IMPLICIT_CALL, value_node)
|
||||
{
|
||||
builder.into_diagnostic(format_args!(
|
||||
"Method `__class_getitem__` of type `{}` \
|
||||
is possibly unbound",
|
||||
"Method `__class_getitem__` of type `{}` may be missing",
|
||||
value_ty.display(db),
|
||||
));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue