Check sequence type before triggering unnecessary-enumerate (FURB148) len suggestion (#7781)

## Summary

Check that the sequence type is a list, set, dict, or tuple before
recommending replacing the `enumerate(...)` call with `range(len(...))`.
Document behaviour so users are aware of the type inference limitation
leading to false negatives.

Closes #7656.
This commit is contained in:
Tom Kuson 2023-10-03 15:39:14 +01:00 committed by GitHub
parent 69b8136463
commit 37d21c0d54
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 416 additions and 214 deletions

View file

@ -485,6 +485,14 @@ impl BuiltinTypeChecker for SetChecker {
const EXPR_TYPE: PythonType = PythonType::Set;
}
struct TupleChecker;
impl BuiltinTypeChecker for TupleChecker {
const BUILTIN_TYPE_NAME: &'static str = "tuple";
const TYPING_NAME: &'static str = "Tuple";
const EXPR_TYPE: PythonType = PythonType::Tuple;
}
/// Test whether the given binding (and the given name) can be considered a list.
/// For this, we check what value might be associated with it through it's initialization and
/// what annotation it has (we consider `list` and `typing.List`).
@ -506,6 +514,14 @@ pub fn is_set(binding: &Binding, semantic: &SemanticModel) -> bool {
check_type::<SetChecker>(binding, semantic)
}
/// Test whether the given binding (and the given name) can be considered a
/// tuple. For this, we check what value might be associated with it through
/// it's initialization and what annotation it has (we consider `tuple` and
/// `typing.Tuple`).
pub fn is_tuple(binding: &Binding, semantic: &SemanticModel) -> bool {
check_type::<TupleChecker>(binding, semantic)
}
/// Find the [`ParameterWithDefault`] corresponding to the given [`Binding`].
#[inline]
fn find_parameter<'a>(