Skip to content

[get_first]: lint on non-primitive slices #11609

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clippy_lints/src/loops/same_item_push.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ fn get_vec_push<'tcx>(
if let StmtKind::Semi(semi_stmt) = &stmt.kind;
if let ExprKind::MethodCall(path, self_expr, args, _) = &semi_stmt.kind;
// Figure out the parameters for the method call
if let Some(pushed_item) = args.get(0);
if let Some(pushed_item) = args.first();
// Check that the method being called is push() on a Vec
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_expr), sym::Vec);
if path.ident.name.as_str() == "push";
Expand Down
4 changes: 2 additions & 2 deletions clippy_lints/src/manual_bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<
if let ExprKind::Path(ref count_func_qpath) = count_func.kind;

if let QPath::Resolved(_, count_func_path) = count_func_qpath;
if let Some(segment_zero) = count_func_path.segments.get(0);
if let Some(segment_zero) = count_func_path.segments.first();
if let Some(args) = segment_zero.args;
if let Some(GenericArg::Type(real_ty)) = args.args.get(0);
if let Some(GenericArg::Type(real_ty)) = args.args.first();

if let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id();
if cx.tcx.is_diagnostic_item(sym::mem_size_of, def_id);
Expand Down
2 changes: 0 additions & 2 deletions clippy_lints/src/methods/get_first.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_slice_of_primitives;
use clippy_utils::source::snippet_with_applicability;
use if_chain::if_chain;
use rustc_ast::LitKind;
Expand All @@ -20,7 +19,6 @@ pub(super) fn check<'tcx>(
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
if cx.tcx.type_of(impl_id).instantiate_identity().is_slice();
if let Some(_) = is_slice_of_primitives(cx, recv);
if let hir::ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = arg.kind;
then {
let mut app = Applicability::MachineApplicable;
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/methods/search_is_some.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub(super) fn check<'tcx>(
if search_method == "find";
if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = search_arg.kind;
let closure_body = cx.tcx.hir().body(body);
if let Some(closure_arg) = closure_body.params.get(0);
if let Some(closure_arg) = closure_body.params.first();
then {
if let hir::PatKind::Ref(..) = closure_arg.pat.kind {
Some(search_snippet.replacen('&', "", 1))
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/missing_doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl MissingDoc {
if_chain! {
if let Some(meta) = meta;
if let MetaItemKind::List(list) = meta.kind;
if let Some(meta) = list.get(0);
if let Some(meta) = list.first();
if let Some(name) = meta.ident();
then {
name.name == sym::include
Expand Down
4 changes: 2 additions & 2 deletions clippy_lints/src/needless_continue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ fn needless_continue_in_else(else_expr: &ast::Expr, label: Option<&ast::Label>)
}

fn is_first_block_stmt_continue(block: &ast::Block, label: Option<&ast::Label>) -> bool {
block.stmts.get(0).map_or(false, |stmt| match stmt.kind {
block.stmts.first().map_or(false, |stmt| match stmt.kind {
ast::StmtKind::Semi(ref e) | ast::StmtKind::Expr(ref e) => {
if let ast::ExprKind::Continue(ref l) = e.kind {
compare_labels(label, l.as_ref())
Expand Down Expand Up @@ -434,7 +434,7 @@ fn erode_from_back(s: &str) -> String {
}

fn span_of_first_expr_in_block(block: &ast::Block) -> Option<Span> {
block.stmts.get(0).map(|stmt| stmt.span)
block.stmts.first().map(|stmt| stmt.span)
}

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/slow_vector_initialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> {

fn visit_block(&mut self, block: &'tcx Block<'_>) {
if self.initialization_found {
if let Some(s) = block.stmts.get(0) {
if let Some(s) = block.stmts.first() {
self.visit_stmt(s);
}

Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/uninit_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ fn extract_set_len_self<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Opt
let expr = peel_hir_expr_while(expr, |e| {
if let ExprKind::Block(block, _) = e.kind {
// Extract the first statement/expression
match (block.stmts.get(0).map(|stmt| &stmt.kind), block.expr) {
match (block.stmts.first().map(|stmt| &stmt.kind), block.expr) {
(None, Some(expr)) => Some(expr),
(Some(StmtKind::Expr(expr) | StmtKind::Semi(expr)), _) => Some(expr),
_ => None,
Expand Down
4 changes: 2 additions & 2 deletions clippy_lints/src/unnecessary_map_on_constructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMapOnConstructor {
let (constructor_path, constructor_item) =
if let hir::ExprKind::Call(constructor, constructor_args) = recv.kind
&& let hir::ExprKind::Path(constructor_path) = constructor.kind
&& let Some(arg) = constructor_args.get(0)
&& let Some(arg) = constructor_args.first()
{
if constructor.span.from_expansion() || arg.span.from_expansion() {
return;
Expand All @@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMapOnConstructor {
_ => return,
}

if let Some(map_arg) = args.get(0)
if let Some(map_arg) = args.first()
&& let hir::ExprKind::Path(fun) = map_arg.kind
{
if map_arg.span.from_expansion() {
Expand Down
2 changes: 1 addition & 1 deletion clippy_utils/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
},
(Some(Constant::Vec(vec)), _) => {
if !vec.is_empty() && vec.iter().all(|x| *x == vec[0]) {
match vec.get(0) {
match vec.first() {
Some(Constant::F32(x)) => Some(Constant::F32(*x)),
Some(Constant::F64(x)) => Some(Constant::F64(*x)),
_ => None,
Expand Down
2 changes: 1 addition & 1 deletion clippy_utils/src/higher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ pub fn get_vec_init_kind<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -
} else if name.ident.name == symbol::kw::Default {
return Some(VecInitKind::Default);
} else if name.ident.name.as_str() == "with_capacity" {
let arg = args.get(0)?;
let arg = args.first()?;
return match constant_simple(cx, cx.typeck_results(), arg) {
Some(Constant::Int(num)) => Some(VecInitKind::WithConstCapacity(num)),
_ => Some(VecInitKind::WithExprCapacity(arg.hir_id)),
Expand Down
13 changes: 10 additions & 3 deletions tests/ui/get_first.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,20 @@ impl Bar {

fn main() {
let x = vec![2, 3, 5];
let _ = x.first(); // Use x.first()
let _ = x.first();
//~^ ERROR: accessing first element with `x.get(0)`
let _ = x.get(1);
let _ = x[0];

let y = [2, 3, 5];
let _ = y.first(); // Use y.first()
let _ = y.first();
//~^ ERROR: accessing first element with `y.get(0)`
let _ = y.get(1);
let _ = y[0];

let z = &[2, 3, 5];
let _ = z.first(); // Use z.first()
let _ = z.first();
//~^ ERROR: accessing first element with `z.get(0)`
let _ = z.get(1);
let _ = z[0];

Expand All @@ -37,4 +40,8 @@ fn main() {

let bar = Bar { arr: [0, 1, 2] };
let _ = bar.get(0); // Do not lint, because Bar is struct.

let non_primitives = [vec![1, 2], vec![3, 4]];
let _ = non_primitives.first();
//~^ ERROR: accessing first element with `non_primitives.get(0)`
}
13 changes: 10 additions & 3 deletions tests/ui/get_first.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,20 @@ impl Bar {

fn main() {
let x = vec![2, 3, 5];
let _ = x.get(0); // Use x.first()
let _ = x.get(0);
//~^ ERROR: accessing first element with `x.get(0)`
let _ = x.get(1);
let _ = x[0];

let y = [2, 3, 5];
let _ = y.get(0); // Use y.first()
let _ = y.get(0);
//~^ ERROR: accessing first element with `y.get(0)`
let _ = y.get(1);
let _ = y[0];

let z = &[2, 3, 5];
let _ = z.get(0); // Use z.first()
let _ = z.get(0);
//~^ ERROR: accessing first element with `z.get(0)`
let _ = z.get(1);
let _ = z[0];

Expand All @@ -37,4 +40,8 @@ fn main() {

let bar = Bar { arr: [0, 1, 2] };
let _ = bar.get(0); // Do not lint, because Bar is struct.

let non_primitives = [vec![1, 2], vec![3, 4]];
let _ = non_primitives.get(0);
//~^ ERROR: accessing first element with `non_primitives.get(0)`
}
18 changes: 12 additions & 6 deletions tests/ui/get_first.stderr
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
error: accessing first element with `x.get(0)`
--> $DIR/get_first.rs:17:13
|
LL | let _ = x.get(0); // Use x.first()
LL | let _ = x.get(0);
| ^^^^^^^^ help: try: `x.first()`
|
= note: `-D clippy::get-first` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::get_first)]`

error: accessing first element with `y.get(0)`
--> $DIR/get_first.rs:22:13
--> $DIR/get_first.rs:23:13
|
LL | let _ = y.get(0); // Use y.first()
LL | let _ = y.get(0);
| ^^^^^^^^ help: try: `y.first()`

error: accessing first element with `z.get(0)`
--> $DIR/get_first.rs:27:13
--> $DIR/get_first.rs:29:13
|
LL | let _ = z.get(0); // Use z.first()
LL | let _ = z.get(0);
| ^^^^^^^^ help: try: `z.first()`

error: aborting due to 3 previous errors
error: accessing first element with `non_primitives.get(0)`
--> $DIR/get_first.rs:45:13
|
LL | let _ = non_primitives.get(0);
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `non_primitives.first()`

error: aborting due to 4 previous errors