disable indexing_slicing for custom Index impls
This commit is contained in:
parent
03654badfd
commit
93b39d8910
@ -3,6 +3,7 @@
|
|||||||
use clippy_utils::consts::{constant, Constant};
|
use clippy_utils::consts::{constant, Constant};
|
||||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||||
use clippy_utils::higher;
|
use clippy_utils::higher;
|
||||||
|
use clippy_utils::ty::{adt_has_inherent_method, deref_chain};
|
||||||
use rustc_ast::ast::RangeLimits;
|
use rustc_ast::ast::RangeLimits;
|
||||||
use rustc_hir::{Expr, ExprKind};
|
use rustc_hir::{Expr, ExprKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
@ -104,7 +105,15 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ExprKind::Index(array, index, _) = &expr.kind {
|
if let ExprKind::Index(array, index, _) = &expr.kind
|
||||||
|
&& let expr_ty = cx.typeck_results().expr_ty(array)
|
||||||
|
&& let mut deref = deref_chain(cx, expr_ty)
|
||||||
|
&& deref.any(|l| {
|
||||||
|
l.peel_refs().is_slice()
|
||||||
|
|| l.peel_refs().is_array()
|
||||||
|
|| adt_has_inherent_method(cx, l.peel_refs(), sym!(get))
|
||||||
|
})
|
||||||
|
{
|
||||||
let note = "the suggestion might not be applicable in constant blocks";
|
let note = "the suggestion might not be applicable in constant blocks";
|
||||||
let ty = cx.typeck_results().expr_ty(array).peel_refs();
|
let ty = cx.typeck_results().expr_ty(array).peel_refs();
|
||||||
if let Some(range) = higher::Range::hir(index) {
|
if let Some(range) = higher::Range::hir(index) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::get_parent_as_impl;
|
use clippy_utils::get_parent_as_impl;
|
||||||
use clippy_utils::source::snippet;
|
use clippy_utils::source::snippet;
|
||||||
use clippy_utils::ty::{implements_trait, make_normalized_projection};
|
use clippy_utils::ty::{adt_has_inherent_method, deref_chain, implements_trait, make_normalized_projection};
|
||||||
use rustc_ast::Mutability;
|
use rustc_ast::Mutability;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{FnRetTy, ImplItemKind, ImplicitSelfKind, ItemKind, TyKind};
|
use rustc_hir::{FnRetTy, ImplItemKind, ImplicitSelfKind, ItemKind, TyKind};
|
||||||
@ -9,8 +9,7 @@
|
|||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
use rustc_session::declare_lint_pass;
|
use rustc_session::declare_lint_pass;
|
||||||
use rustc_span::{sym, Symbol};
|
use rustc_span::sym;
|
||||||
use std::iter;
|
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
@ -124,33 +123,6 @@ fn is_ty_exported(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
|
|||||||
.is_some_and(|did| cx.effective_visibilities.is_exported(did))
|
.is_some_and(|did| cx.effective_visibilities.is_exported(did))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the deref chain of a type, starting with the type itself.
|
|
||||||
fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl Iterator<Item = Ty<'tcx>> + 'cx {
|
|
||||||
iter::successors(Some(ty), |&ty| {
|
|
||||||
if let Some(deref_did) = cx.tcx.lang_items().deref_trait()
|
|
||||||
&& implements_trait(cx, ty, deref_did, &[])
|
|
||||||
{
|
|
||||||
make_normalized_projection(cx.tcx, cx.param_env, deref_did, sym::Target, [ty])
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn adt_has_inherent_method(cx: &LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> bool {
|
|
||||||
if let Some(ty_did) = ty.ty_adt_def().map(ty::AdtDef::did) {
|
|
||||||
cx.tcx.inherent_impls(ty_did).into_iter().flatten().any(|&did| {
|
|
||||||
cx.tcx
|
|
||||||
.associated_items(did)
|
|
||||||
.filter_by_name_unhygienic(method_name)
|
|
||||||
.next()
|
|
||||||
.is_some_and(|item| item.kind == ty::AssocKind::Fn)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LateLintPass<'_> for IterWithoutIntoIter {
|
impl LateLintPass<'_> for IterWithoutIntoIter {
|
||||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) {
|
fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) {
|
||||||
if !in_external_macro(cx.sess(), item.span)
|
if !in_external_macro(cx.sess(), item.span)
|
||||||
|
@ -1328,3 +1328,33 @@ pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>
|
|||||||
pub fn is_manually_drop(ty: Ty<'_>) -> bool {
|
pub fn is_manually_drop(ty: Ty<'_>) -> bool {
|
||||||
ty.ty_adt_def().map_or(false, AdtDef::is_manually_drop)
|
ty.ty_adt_def().map_or(false, AdtDef::is_manually_drop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the deref chain of a type, starting with the type itself.
|
||||||
|
pub fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl Iterator<Item = Ty<'tcx>> + 'cx {
|
||||||
|
iter::successors(Some(ty), |&ty| {
|
||||||
|
if let Some(deref_did) = cx.tcx.lang_items().deref_trait()
|
||||||
|
&& implements_trait(cx, ty, deref_did, &[])
|
||||||
|
{
|
||||||
|
make_normalized_projection(cx.tcx, cx.param_env, deref_did, sym::Target, [ty])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if a Ty<'_> has some inherent method Symbol.
|
||||||
|
/// This does not look for impls in the type's Deref::Target type.
|
||||||
|
/// If you need this, you should wrap this call in clippy_utils::ty::deref_chain().any(...).
|
||||||
|
pub fn adt_has_inherent_method(cx: &LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> bool {
|
||||||
|
if let Some(ty_did) = ty.ty_adt_def().map(ty::AdtDef::did) {
|
||||||
|
cx.tcx.inherent_impls(ty_did).into_iter().flatten().any(|&did| {
|
||||||
|
cx.tcx
|
||||||
|
.associated_items(did)
|
||||||
|
.filter_by_name_unhygienic(method_name)
|
||||||
|
.next()
|
||||||
|
.is_some_and(|item| item.kind == ty::AssocKind::Fn)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,6 +3,21 @@
|
|||||||
// we want to avoid false positives.
|
// we want to avoid false positives.
|
||||||
#![warn(clippy::out_of_bounds_indexing)]
|
#![warn(clippy::out_of_bounds_indexing)]
|
||||||
#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::useless_vec)]
|
#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::useless_vec)]
|
||||||
|
#![warn(clippy::indexing_slicing)]
|
||||||
|
|
||||||
|
use std::ops::Index;
|
||||||
|
|
||||||
|
struct BoolMap<T> {
|
||||||
|
false_value: T,
|
||||||
|
true_value: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Index<bool> for BoolMap<T> {
|
||||||
|
type Output = T;
|
||||||
|
fn index(&self, index: bool) -> &T {
|
||||||
|
if index { &self.true_value } else { &self.false_value }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = [1, 2, 3, 4];
|
let x = [1, 2, 3, 4];
|
||||||
@ -51,4 +66,11 @@ fn main() {
|
|||||||
//~^ ERROR: slicing may panic
|
//~^ ERROR: slicing may panic
|
||||||
|
|
||||||
&v[..]; // Ok, should not produce stderr.
|
&v[..]; // Ok, should not produce stderr.
|
||||||
|
|
||||||
|
let map = BoolMap {
|
||||||
|
false_value: 2,
|
||||||
|
true_value: 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
map[true]; // Ok, because `get` does not exist (custom indexing)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error: slicing may panic
|
error: slicing may panic
|
||||||
--> tests/ui/indexing_slicing_slice.rs:12:6
|
--> tests/ui/indexing_slicing_slice.rs:27:6
|
||||||
|
|
|
|
||||||
LL | &x[index..];
|
LL | &x[index..];
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
@ -9,7 +9,7 @@ LL | &x[index..];
|
|||||||
= help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]`
|
= help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]`
|
||||||
|
|
||||||
error: slicing may panic
|
error: slicing may panic
|
||||||
--> tests/ui/indexing_slicing_slice.rs:14:6
|
--> tests/ui/indexing_slicing_slice.rs:29:6
|
||||||
|
|
|
|
||||||
LL | &x[..index];
|
LL | &x[..index];
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
@ -17,7 +17,7 @@ LL | &x[..index];
|
|||||||
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
|
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
|
||||||
|
|
||||||
error: slicing may panic
|
error: slicing may panic
|
||||||
--> tests/ui/indexing_slicing_slice.rs:16:6
|
--> tests/ui/indexing_slicing_slice.rs:31:6
|
||||||
|
|
|
|
||||||
LL | &x[index_from..index_to];
|
LL | &x[index_from..index_to];
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -25,7 +25,7 @@ LL | &x[index_from..index_to];
|
|||||||
= help: consider using `.get(n..m)` or `.get_mut(n..m)` instead
|
= help: consider using `.get(n..m)` or `.get_mut(n..m)` instead
|
||||||
|
|
||||||
error: slicing may panic
|
error: slicing may panic
|
||||||
--> tests/ui/indexing_slicing_slice.rs:18:6
|
--> tests/ui/indexing_slicing_slice.rs:33:6
|
||||||
|
|
|
|
||||||
LL | &x[index_from..][..index_to];
|
LL | &x[index_from..][..index_to];
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -33,7 +33,7 @@ LL | &x[index_from..][..index_to];
|
|||||||
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
|
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
|
||||||
|
|
||||||
error: slicing may panic
|
error: slicing may panic
|
||||||
--> tests/ui/indexing_slicing_slice.rs:18:6
|
--> tests/ui/indexing_slicing_slice.rs:33:6
|
||||||
|
|
|
|
||||||
LL | &x[index_from..][..index_to];
|
LL | &x[index_from..][..index_to];
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
@ -41,7 +41,7 @@ LL | &x[index_from..][..index_to];
|
|||||||
= help: consider using `.get(n..)` or .get_mut(n..)` instead
|
= help: consider using `.get(n..)` or .get_mut(n..)` instead
|
||||||
|
|
||||||
error: slicing may panic
|
error: slicing may panic
|
||||||
--> tests/ui/indexing_slicing_slice.rs:21:6
|
--> tests/ui/indexing_slicing_slice.rs:36:6
|
||||||
|
|
|
|
||||||
LL | &x[5..][..10];
|
LL | &x[5..][..10];
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
@ -49,7 +49,7 @@ LL | &x[5..][..10];
|
|||||||
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
|
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
|
||||||
|
|
||||||
error: range is out of bounds
|
error: range is out of bounds
|
||||||
--> tests/ui/indexing_slicing_slice.rs:21:8
|
--> tests/ui/indexing_slicing_slice.rs:36:8
|
||||||
|
|
|
|
||||||
LL | &x[5..][..10];
|
LL | &x[5..][..10];
|
||||||
| ^
|
| ^
|
||||||
@ -58,7 +58,7 @@ LL | &x[5..][..10];
|
|||||||
= help: to override `-D warnings` add `#[allow(clippy::out_of_bounds_indexing)]`
|
= help: to override `-D warnings` add `#[allow(clippy::out_of_bounds_indexing)]`
|
||||||
|
|
||||||
error: slicing may panic
|
error: slicing may panic
|
||||||
--> tests/ui/indexing_slicing_slice.rs:25:6
|
--> tests/ui/indexing_slicing_slice.rs:40:6
|
||||||
|
|
|
|
||||||
LL | &x[0..][..3];
|
LL | &x[0..][..3];
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
@ -66,7 +66,7 @@ LL | &x[0..][..3];
|
|||||||
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
|
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
|
||||||
|
|
||||||
error: slicing may panic
|
error: slicing may panic
|
||||||
--> tests/ui/indexing_slicing_slice.rs:27:6
|
--> tests/ui/indexing_slicing_slice.rs:42:6
|
||||||
|
|
|
|
||||||
LL | &x[1..][..5];
|
LL | &x[1..][..5];
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
@ -74,19 +74,19 @@ LL | &x[1..][..5];
|
|||||||
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
|
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
|
||||||
|
|
||||||
error: range is out of bounds
|
error: range is out of bounds
|
||||||
--> tests/ui/indexing_slicing_slice.rs:35:12
|
--> tests/ui/indexing_slicing_slice.rs:50:12
|
||||||
|
|
|
|
||||||
LL | &y[0..=4];
|
LL | &y[0..=4];
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: range is out of bounds
|
error: range is out of bounds
|
||||||
--> tests/ui/indexing_slicing_slice.rs:37:11
|
--> tests/ui/indexing_slicing_slice.rs:52:11
|
||||||
|
|
|
|
||||||
LL | &y[..=4];
|
LL | &y[..=4];
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: slicing may panic
|
error: slicing may panic
|
||||||
--> tests/ui/indexing_slicing_slice.rs:43:6
|
--> tests/ui/indexing_slicing_slice.rs:58:6
|
||||||
|
|
|
|
||||||
LL | &v[10..100];
|
LL | &v[10..100];
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
@ -94,7 +94,7 @@ LL | &v[10..100];
|
|||||||
= help: consider using `.get(n..m)` or `.get_mut(n..m)` instead
|
= help: consider using `.get(n..m)` or `.get_mut(n..m)` instead
|
||||||
|
|
||||||
error: slicing may panic
|
error: slicing may panic
|
||||||
--> tests/ui/indexing_slicing_slice.rs:45:6
|
--> tests/ui/indexing_slicing_slice.rs:60:6
|
||||||
|
|
|
|
||||||
LL | &x[10..][..100];
|
LL | &x[10..][..100];
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
@ -102,13 +102,13 @@ LL | &x[10..][..100];
|
|||||||
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
|
= help: consider using `.get(..n)`or `.get_mut(..n)` instead
|
||||||
|
|
||||||
error: range is out of bounds
|
error: range is out of bounds
|
||||||
--> tests/ui/indexing_slicing_slice.rs:45:8
|
--> tests/ui/indexing_slicing_slice.rs:60:8
|
||||||
|
|
|
|
||||||
LL | &x[10..][..100];
|
LL | &x[10..][..100];
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: slicing may panic
|
error: slicing may panic
|
||||||
--> tests/ui/indexing_slicing_slice.rs:48:6
|
--> tests/ui/indexing_slicing_slice.rs:63:6
|
||||||
|
|
|
|
||||||
LL | &v[10..];
|
LL | &v[10..];
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
@ -116,7 +116,7 @@ LL | &v[10..];
|
|||||||
= help: consider using `.get(n..)` or .get_mut(n..)` instead
|
= help: consider using `.get(n..)` or .get_mut(n..)` instead
|
||||||
|
|
||||||
error: slicing may panic
|
error: slicing may panic
|
||||||
--> tests/ui/indexing_slicing_slice.rs:50:6
|
--> tests/ui/indexing_slicing_slice.rs:65:6
|
||||||
|
|
|
|
||||||
LL | &v[..100];
|
LL | &v[..100];
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
Loading…
Reference in New Issue
Block a user