diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 92facbbf034..dfea0bf18d1 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -1,9 +1,10 @@ //! lint on indexing and slicing operations use clippy_utils::consts::{constant, Constant}; -use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::higher; use rustc_ast::ast::RangeLimits; +use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; @@ -86,18 +87,20 @@ #[derive(Copy, Clone)] pub struct IndexingSlicing { - suppress_lint_in_const: bool, + suppress_restriction_lint_in_const: bool, } impl IndexingSlicing { - pub fn new(suppress_lint_in_const: bool) -> Self { - Self { suppress_lint_in_const } + pub fn new(suppress_restriction_lint_in_const: bool) -> Self { + Self { + suppress_restriction_lint_in_const, + } } } impl<'tcx> LateLintPass<'tcx> for IndexingSlicing { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if self.suppress_lint_in_const && cx.tcx.hir().is_inside_const_context(expr.hir_id) { + if self.suppress_restriction_lint_in_const && cx.tcx.hir().is_inside_const_context(expr.hir_id) { return; } @@ -152,12 +155,19 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { (None, None) => return, // [..] is ok. }; - span_lint_and_help(cx, INDEXING_SLICING, expr.span, "slicing may panic", None, help_msg); + span_lint_and_then(cx, INDEXING_SLICING, expr.span, "slicing may panic", |diag| { + let note = if cx.tcx.hir().is_inside_const_context(expr.hir_id) { + "the suggestion might not be applicable in constant blocks" + } else { + "" + }; + diag.span_suggestion(expr.span, help_msg, note, Applicability::MachineApplicable); + }); } else { // Catchall non-range index, i.e., [n] or [n << m] if let ty::Array(..) = ty.kind() { // Index is a const block. - if self.suppress_lint_in_const && let ExprKind::ConstBlock(..) = index.kind { + if self.suppress_restriction_lint_in_const && let ExprKind::ConstBlock(..) = index.kind { return; } // Index is a constant uint. @@ -167,14 +177,19 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { } } - span_lint_and_help( - cx, - INDEXING_SLICING, - expr.span, - "indexing may panic", - None, - "consider using `.get(n)` or `.get_mut(n)` instead", - ); + span_lint_and_then(cx, INDEXING_SLICING, expr.span, "indexing may panic", |diag| { + let note = if cx.tcx.hir().is_inside_const_context(expr.hir_id) { + "the suggestion might not be applicable in constant blocks" + } else { + "" + }; + diag.span_suggestion( + expr.span, + "consider using `.get(n)` or `.get_mut(n)` instead", + note, + Applicability::MachineApplicable, + ); + }); } } } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3b5bac644ef..2dc3a082277 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -562,7 +562,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: let avoid_breaking_exported_api = conf.avoid_breaking_exported_api; let allow_expect_in_tests = conf.allow_expect_in_tests; let allow_unwrap_in_tests = conf.allow_unwrap_in_tests; - let suppress_lint_in_const = conf.suppress_lint_in_const; + let suppress_restriction_lint_in_const = conf.suppress_restriction_lint_in_const; store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv()))); store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv))); store.register_late_pass(move |_| { @@ -685,7 +685,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(inherent_impl::MultipleInherentImpl)); store.register_late_pass(|_| Box::new(neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd)); store.register_late_pass(|_| Box::new(unwrap::Unwrap)); - store.register_late_pass(move |_| Box::new(indexing_slicing::IndexingSlicing::new(suppress_lint_in_const))); + store.register_late_pass(move |_| { + Box::new(indexing_slicing::IndexingSlicing::new( + suppress_restriction_lint_in_const, + )) + }); store.register_late_pass(|_| Box::new(non_copy_const::NonCopyConst)); store.register_late_pass(|_| Box::new(ptr_offset_with_cast::PtrOffsetWithCast)); store.register_late_pass(|_| Box::new(redundant_clone::RedundantClone)); diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 4a0e135db83..0022044ea41 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -408,8 +408,12 @@ pub(crate) fn get_configuration_metadata() -> Vec { (allow_mixed_uninlined_format_args: bool = true), /// Lint: INDEXING_SLICING /// - /// Whether to suppress lint in const function - (suppress_lint_in_const: bool = true), + /// Whether to suppress a restriction lint in constant code. In same + /// cases the restructured operation might not be unavoidable, as the + /// suggested counterparts are unavailable in constant code. This + /// configuration will cause restriction lints to trigger even + /// if no suggestion can be made. + (suppress_restriction_lint_in_const: bool = true), } /// Search for the configuration file. diff --git a/tests/ui-toml/suppress_lint_in_const/clippy.toml b/tests/ui-toml/suppress_lint_in_const/clippy.toml index fd459ff5ac5..d458f53a73d 100644 --- a/tests/ui-toml/suppress_lint_in_const/clippy.toml +++ b/tests/ui-toml/suppress_lint_in_const/clippy.toml @@ -1 +1 @@ -suppress-lint-in-const = false \ No newline at end of file +suppress-restriction-lint-in-const = false \ No newline at end of file diff --git a/tests/ui-toml/suppress_lint_in_const/test.stderr b/tests/ui-toml/suppress_lint_in_const/test.stderr index b4f6fe0c024..4e4583ab33c 100644 --- a/tests/ui-toml/suppress_lint_in_const/test.stderr +++ b/tests/ui-toml/suppress_lint_in_const/test.stderr @@ -2,9 +2,8 @@ error: indexing may panic --> $DIR/test.rs:11:9 | LL | self.value[0] & 0b1000_0000 != 0 - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ help: consider using `.get(n)` or `.get_mut(n)` instead: `the suggestion might not be applicable in constant blocks` | - = help: consider using `.get(n)` or `.get_mut(n)` instead = note: `-D clippy::indexing-slicing` implied by `-D warnings` error: aborting due to previous error diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index 521af13fe03..6ef2abb15b2 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -35,7 +35,7 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie pass-by-value-size-limit single-char-binding-names-threshold standard-macro-braces - suppress-lint-in-const + suppress-restriction-lint-in-const third-party too-large-for-stack too-many-arguments-threshold diff --git a/tests/ui/indexing_slicing_index.stderr b/tests/ui/indexing_slicing_index.stderr index d8b6e3f1262..30fb6990795 100644 --- a/tests/ui/indexing_slicing_index.stderr +++ b/tests/ui/indexing_slicing_index.stderr @@ -14,50 +14,39 @@ error: indexing may panic --> $DIR/indexing_slicing_index.rs:22:5 | LL | x[index]; - | ^^^^^^^^ + | ^^^^^^^^ help: consider using `.get(n)` or `.get_mut(n)` instead | - = help: consider using `.get(n)` or `.get_mut(n)` instead = note: `-D clippy::indexing-slicing` implied by `-D warnings` error: indexing may panic --> $DIR/indexing_slicing_index.rs:38:5 | LL | v[0]; - | ^^^^ - | - = help: consider using `.get(n)` or `.get_mut(n)` instead + | ^^^^ help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic --> $DIR/indexing_slicing_index.rs:39:5 | LL | v[10]; - | ^^^^^ - | - = help: consider using `.get(n)` or `.get_mut(n)` instead + | ^^^^^ help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic --> $DIR/indexing_slicing_index.rs:40:5 | LL | v[1 << 3]; - | ^^^^^^^^^ - | - = help: consider using `.get(n)` or `.get_mut(n)` instead + | ^^^^^^^^^ help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic --> $DIR/indexing_slicing_index.rs:46:5 | LL | v[N]; - | ^^^^ - | - = help: consider using `.get(n)` or `.get_mut(n)` instead + | ^^^^ help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic --> $DIR/indexing_slicing_index.rs:47:5 | LL | v[M]; - | ^^^^ - | - = help: consider using `.get(n)` or `.get_mut(n)` instead + | ^^^^ help: consider using `.get(n)` or `.get_mut(n)` instead error[E0080]: evaluation of constant value failed --> $DIR/indexing_slicing_index.rs:10:24 diff --git a/tests/ui/indexing_slicing_slice.stderr b/tests/ui/indexing_slicing_slice.stderr index dc54bd41365..ac2cc009a22 100644 --- a/tests/ui/indexing_slicing_slice.stderr +++ b/tests/ui/indexing_slicing_slice.stderr @@ -2,50 +2,39 @@ error: slicing may panic --> $DIR/indexing_slicing_slice.rs:12:6 | LL | &x[index..]; - | ^^^^^^^^^^ + | ^^^^^^^^^^ help: consider using `.get(n..)` or .get_mut(n..)` instead | - = help: consider using `.get(n..)` or .get_mut(n..)` instead = note: `-D clippy::indexing-slicing` implied by `-D warnings` error: slicing may panic --> $DIR/indexing_slicing_slice.rs:13:6 | 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 --> $DIR/indexing_slicing_slice.rs:14:6 | 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 --> $DIR/indexing_slicing_slice.rs:15:6 | LL | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..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 --> $DIR/indexing_slicing_slice.rs:15:6 | LL | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..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 --> $DIR/indexing_slicing_slice.rs:16:6 | LL | &x[5..][..10]; // Two lint reports, one for out of bounds [5..] and another for slicing [..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 --> $DIR/indexing_slicing_slice.rs:16:8 @@ -59,17 +48,13 @@ error: slicing may panic --> $DIR/indexing_slicing_slice.rs:17:6 | 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 --> $DIR/indexing_slicing_slice.rs:18:6 | 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 --> $DIR/indexing_slicing_slice.rs:25:12 @@ -87,17 +72,13 @@ error: slicing may panic --> $DIR/indexing_slicing_slice.rs:31:6 | 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 --> $DIR/indexing_slicing_slice.rs:32:6 | LL | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..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 --> $DIR/indexing_slicing_slice.rs:32:8 @@ -109,17 +90,13 @@ error: slicing may panic --> $DIR/indexing_slicing_slice.rs:33:6 | 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 --> $DIR/indexing_slicing_slice.rs:34:6 | LL | &v[..100]; - | ^^^^^^^^ - | - = help: consider using `.get(..n)`or `.get_mut(..n)` instead + | ^^^^^^^^ help: consider using `.get(..n)`or `.get_mut(..n)` instead error: aborting due to 16 previous errors