Skip to content

Commit

Permalink
add io_other_error lint
Browse files Browse the repository at this point in the history
  • Loading branch information
llogiq committed Jan 18, 2025
1 parent e359e88 commit d940211
Show file tree
Hide file tree
Showing 12 changed files with 213 additions and 30 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5682,6 +5682,7 @@ Released 2018-09-13
[`invalid_utf8_in_unchecked`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_utf8_in_unchecked
[`inverted_saturating_sub`]: https://rust-lang.github.io/rust-clippy/master/index.html#inverted_saturating_sub
[`invisible_characters`]: https://rust-lang.github.io/rust-clippy/master/index.html#invisible_characters
[`io_other_error`]: https://rust-lang.github.io/rust-clippy/master/index.html#io_other_error
[`is_digit_ascii_radix`]: https://rust-lang.github.io/rust-clippy/master/index.html#is_digit_ascii_radix
[`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements
[`items_after_test_module`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_test_module
Expand Down
5 changes: 2 additions & 3 deletions clippy_dev/src/new_lint.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use crate::utils::{clippy_project_root, clippy_version};
use indoc::{formatdoc, writedoc};
use std::fmt;
use std::fmt::Write as _;
use std::fs::{self, OpenOptions};
use std::io::prelude::*;
use std::io::{self, ErrorKind};
use std::path::{Path, PathBuf};
use std::{fmt, io};

struct LintData<'a> {
pass: &'a str,
Expand All @@ -25,7 +24,7 @@ impl<T> Context for io::Result<T> {
Ok(t) => Ok(t),
Err(e) => {
let message = format!("{}: {e}", text.as_ref());
Err(io::Error::new(ErrorKind::Other, message))
Err(io::Error::other(message))
},
}
}
Expand Down
1 change: 1 addition & 0 deletions clippy_lints/src/declared_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::int_plus_one::INT_PLUS_ONE_INFO,
crate::integer_division_remainder_used::INTEGER_DIVISION_REMAINDER_USED_INFO,
crate::invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS_INFO,
crate::io_other_error::IO_OTHER_ERROR_INFO,
crate::item_name_repetitions::ENUM_VARIANT_NAMES_INFO,
crate::item_name_repetitions::MODULE_INCEPTION_INFO,
crate::item_name_repetitions::MODULE_NAME_REPETITIONS_INFO,
Expand Down
74 changes: 74 additions & 0 deletions clippy_lints/src/io_other_error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{IO_ERROR_OTHER, Msrv};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass;

declare_clippy_lint! {
/// ### What it does
/// This lint warns on calling `io::Error::new(..)` with a kind of
/// `io::ErrorKind::Other`.
///
/// ### Why is this bad?
/// Since Rust 1.74, there's the `io::Error::other(_)` shortcut.
///
/// ### Example
/// ```no_run
/// use std::io;
/// let _ = io::Error::new(io::ErrorKind::Other, "bad".to_string());
/// ```
/// Use instead:
/// ```no_run
/// let _ = io::Error::other("bad".to_string());
/// ```
#[clippy::version = "1.86.0"]
pub IO_OTHER_ERROR,
complexity,
"calling `io::Error::new(io::ErrorKind::Other, _)`"
}

pub struct IoOtherError {
msrv: Msrv,
}

impl_lint_pass!(IoOtherError => [IO_OTHER_ERROR]);

impl IoOtherError {
pub fn new(conf: &'static Conf) -> Self {
Self {
msrv: conf.msrv.clone(),
}
}
}

impl LateLintPass<'_> for IoOtherError {
extract_msrv_attr!(LateContext);

fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
if let ExprKind::Call(path, [error_kind, error]) = expr.kind
&& !expr.span.from_expansion()
&& !error_kind.span.from_expansion()
&& clippy_utils::is_expr_path_def_path(cx, path, &clippy_utils::paths::IO_ERROR_NEW)
&& clippy_utils::is_expr_path_def_path(
cx,
clippy_utils::expr_or_init(cx, error_kind),
&clippy_utils::paths::IO_ERRORKIND_OTHER,
)
&& self.msrv.meets(IO_ERROR_OTHER)
{
let mut applicability = Applicability::MachineApplicable;
let snip = clippy_utils::source::snippet_with_applicability(cx, error.span, "_", &mut applicability);
span_lint_and_sugg(
cx,
IO_OTHER_ERROR,
expr.span,
"this can be `io::Error::other`",
"use",
format!("std::io::Error::other({snip})"),
applicability,
);
}
}
}
2 changes: 2 additions & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ mod instant_subtraction;
mod int_plus_one;
mod integer_division_remainder_used;
mod invalid_upcast_comparisons;
mod io_other_error;
mod item_name_repetitions;
mod items_after_statements;
mod items_after_test_module;
Expand Down Expand Up @@ -972,5 +973,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
store.register_late_pass(|_| Box::new(unnecessary_literal_bound::UnnecessaryLiteralBound));
store.register_late_pass(move |_| Box::new(arbitrary_source_item_ordering::ArbitrarySourceItemOrdering::new(conf)));
store.register_late_pass(|_| Box::new(unneeded_struct_pattern::UnneededStructPattern));
store.register_late_pass(move |_| Box::new(io_other_error::IoOtherError::new(conf)));
// add lints here, do not remove this comment, it's used in `new_lint`
}
2 changes: 1 addition & 1 deletion clippy_utils/src/msrvs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ msrv_aliases! {
1,80,0 { BOX_INTO_ITER }
1,77,0 { C_STR_LITERALS }
1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT }
1,74,0 { REPR_RUST }
1,74,0 { REPR_RUST, IO_ERROR_OTHER }
1,73,0 { MANUAL_DIV_CEIL }
1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE }
1,70,0 { OPTION_RESULT_IS_VARIANT_AND, BINARY_HEAP_RETAIN }
Expand Down
2 changes: 2 additions & 0 deletions clippy_utils/src/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub const CHILD_KILL: [&str; 4] = ["std", "process", "Child", "kill"];
pub const PANIC_ANY: [&str; 3] = ["std", "panic", "panic_any"];
pub const CHAR_IS_ASCII: [&str; 5] = ["core", "char", "methods", "<impl char>", "is_ascii"];
pub const STDIN: [&str; 4] = ["std", "io", "stdio", "Stdin"];
pub const IO_ERROR_NEW: [&str; 5] = ["std", "io", "error", "Error", "new"];
pub const IO_ERRORKIND_OTHER: [&str; 5] = ["std", "io", "error", "ErrorKind", "Other"];

// Paths in clippy itself
pub const MSRV: [&str; 3] = ["clippy_utils", "msrvs", "Msrv"];
Expand Down
7 changes: 6 additions & 1 deletion tests/ui/format_args_unfixable.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#![warn(clippy::format_in_format_args, clippy::to_string_in_format_args)]
#![allow(unused)]
#![allow(clippy::assertions_on_constants, clippy::eq_op, clippy::uninlined_format_args)]
#![allow(
clippy::assertions_on_constants,
clippy::eq_op,
clippy::uninlined_format_args,
clippy::io_other_error
)]

use std::io::{Error, ErrorKind, Write, stdout};
use std::ops::Deref;
Expand Down
50 changes: 25 additions & 25 deletions tests/ui/format_args_unfixable.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: `format!` in `println!` args
--> tests/ui/format_args_unfixable.rs:26:5
--> tests/ui/format_args_unfixable.rs:31:5
|
LL | println!("error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -10,7 +10,7 @@ LL | println!("error: {}", format!("something failed at {}", Location::calle
= help: to override `-D warnings` add `#[allow(clippy::format_in_format_args)]`

error: `format!` in `println!` args
--> tests/ui/format_args_unfixable.rs:28:5
--> tests/ui/format_args_unfixable.rs:33:5
|
LL | println!("{}: {}", error, format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -19,7 +19,7 @@ LL | println!("{}: {}", error, format!("something failed at {}", Location::c
= help: or consider changing `format!` to `format_args!`

error: `format!` in `println!` args
--> tests/ui/format_args_unfixable.rs:30:5
--> tests/ui/format_args_unfixable.rs:35:5
|
LL | println!("{:?}: {}", error, format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -28,7 +28,7 @@ LL | println!("{:?}: {}", error, format!("something failed at {}", Location:
= help: or consider changing `format!` to `format_args!`

error: `format!` in `println!` args
--> tests/ui/format_args_unfixable.rs:32:5
--> tests/ui/format_args_unfixable.rs:37:5
|
LL | println!("{{}}: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -37,7 +37,7 @@ LL | println!("{{}}: {}", format!("something failed at {}", Location::caller
= help: or consider changing `format!` to `format_args!`

error: `format!` in `println!` args
--> tests/ui/format_args_unfixable.rs:34:5
--> tests/ui/format_args_unfixable.rs:39:5
|
LL | println!(r#"error: "{}""#, format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -46,7 +46,7 @@ LL | println!(r#"error: "{}""#, format!("something failed at {}", Location::
= help: or consider changing `format!` to `format_args!`

error: `format!` in `println!` args
--> tests/ui/format_args_unfixable.rs:36:5
--> tests/ui/format_args_unfixable.rs:41:5
|
LL | println!("error: {}", format!(r#"something failed at "{}""#, Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -55,7 +55,7 @@ LL | println!("error: {}", format!(r#"something failed at "{}""#, Location::
= help: or consider changing `format!` to `format_args!`

error: `format!` in `println!` args
--> tests/ui/format_args_unfixable.rs:38:5
--> tests/ui/format_args_unfixable.rs:43:5
|
LL | println!("error: {}", format!("something failed at {} {0}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -64,7 +64,7 @@ LL | println!("error: {}", format!("something failed at {} {0}", Location::c
= help: or consider changing `format!` to `format_args!`

error: `format!` in `format!` args
--> tests/ui/format_args_unfixable.rs:40:13
--> tests/ui/format_args_unfixable.rs:45:13
|
LL | let _ = format!("error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -73,7 +73,7 @@ LL | let _ = format!("error: {}", format!("something failed at {}", Location
= help: or consider changing `format!` to `format_args!`

error: `format!` in `write!` args
--> tests/ui/format_args_unfixable.rs:42:13
--> tests/ui/format_args_unfixable.rs:47:13
|
LL | let _ = write!(
| _____________^
Expand All @@ -88,7 +88,7 @@ LL | | );
= help: or consider changing `format!` to `format_args!`

error: `format!` in `writeln!` args
--> tests/ui/format_args_unfixable.rs:48:13
--> tests/ui/format_args_unfixable.rs:53:13
|
LL | let _ = writeln!(
| _____________^
Expand All @@ -103,7 +103,7 @@ LL | | );
= help: or consider changing `format!` to `format_args!`

error: `format!` in `print!` args
--> tests/ui/format_args_unfixable.rs:54:5
--> tests/ui/format_args_unfixable.rs:59:5
|
LL | print!("error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -112,7 +112,7 @@ LL | print!("error: {}", format!("something failed at {}", Location::caller(
= help: or consider changing `format!` to `format_args!`

error: `format!` in `eprint!` args
--> tests/ui/format_args_unfixable.rs:56:5
--> tests/ui/format_args_unfixable.rs:61:5
|
LL | eprint!("error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -121,7 +121,7 @@ LL | eprint!("error: {}", format!("something failed at {}", Location::caller
= help: or consider changing `format!` to `format_args!`

error: `format!` in `eprintln!` args
--> tests/ui/format_args_unfixable.rs:58:5
--> tests/ui/format_args_unfixable.rs:63:5
|
LL | eprintln!("error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -130,7 +130,7 @@ LL | eprintln!("error: {}", format!("something failed at {}", Location::call
= help: or consider changing `format!` to `format_args!`

error: `format!` in `format_args!` args
--> tests/ui/format_args_unfixable.rs:60:13
--> tests/ui/format_args_unfixable.rs:65:13
|
LL | let _ = format_args!("error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -139,7 +139,7 @@ LL | let _ = format_args!("error: {}", format!("something failed at {}", Loc
= help: or consider changing `format!` to `format_args!`

error: `format!` in `assert!` args
--> tests/ui/format_args_unfixable.rs:62:5
--> tests/ui/format_args_unfixable.rs:67:5
|
LL | assert!(true, "error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -148,7 +148,7 @@ LL | assert!(true, "error: {}", format!("something failed at {}", Location::
= help: or consider changing `format!` to `format_args!`

error: `format!` in `assert_eq!` args
--> tests/ui/format_args_unfixable.rs:64:5
--> tests/ui/format_args_unfixable.rs:69:5
|
LL | assert_eq!(0, 0, "error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -157,7 +157,7 @@ LL | assert_eq!(0, 0, "error: {}", format!("something failed at {}", Locatio
= help: or consider changing `format!` to `format_args!`

error: `format!` in `assert_ne!` args
--> tests/ui/format_args_unfixable.rs:66:5
--> tests/ui/format_args_unfixable.rs:71:5
|
LL | assert_ne!(0, 0, "error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -166,7 +166,7 @@ LL | assert_ne!(0, 0, "error: {}", format!("something failed at {}", Locatio
= help: or consider changing `format!` to `format_args!`

error: `format!` in `panic!` args
--> tests/ui/format_args_unfixable.rs:68:5
--> tests/ui/format_args_unfixable.rs:73:5
|
LL | panic!("error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -175,7 +175,7 @@ LL | panic!("error: {}", format!("something failed at {}", Location::caller(
= help: or consider changing `format!` to `format_args!`

error: `format!` in `usr_println!` args
--> tests/ui/format_args_unfixable.rs:136:5
--> tests/ui/format_args_unfixable.rs:141:5
|
LL | usr_println!(true, "error: {}", format!("boom at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -184,7 +184,7 @@ LL | usr_println!(true, "error: {}", format!("boom at {}", Location::caller(
= help: or consider changing `format!` to `format_args!`

error: `format!` in `usr_println!` args
--> tests/ui/format_args_unfixable.rs:138:5
--> tests/ui/format_args_unfixable.rs:143:5
|
LL | usr_println!(true, "{}: {}", error, format!("boom at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -193,7 +193,7 @@ LL | usr_println!(true, "{}: {}", error, format!("boom at {}", Location::cal
= help: or consider changing `format!` to `format_args!`

error: `format!` in `usr_println!` args
--> tests/ui/format_args_unfixable.rs:140:5
--> tests/ui/format_args_unfixable.rs:145:5
|
LL | usr_println!(true, "{:?}: {}", error, format!("boom at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -202,7 +202,7 @@ LL | usr_println!(true, "{:?}: {}", error, format!("boom at {}", Location::c
= help: or consider changing `format!` to `format_args!`

error: `format!` in `usr_println!` args
--> tests/ui/format_args_unfixable.rs:142:5
--> tests/ui/format_args_unfixable.rs:147:5
|
LL | usr_println!(true, "{{}}: {}", format!("boom at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -211,7 +211,7 @@ LL | usr_println!(true, "{{}}: {}", format!("boom at {}", Location::caller()
= help: or consider changing `format!` to `format_args!`

error: `format!` in `usr_println!` args
--> tests/ui/format_args_unfixable.rs:144:5
--> tests/ui/format_args_unfixable.rs:149:5
|
LL | usr_println!(true, r#"error: "{}""#, format!("boom at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -220,7 +220,7 @@ LL | usr_println!(true, r#"error: "{}""#, format!("boom at {}", Location::ca
= help: or consider changing `format!` to `format_args!`

error: `format!` in `usr_println!` args
--> tests/ui/format_args_unfixable.rs:146:5
--> tests/ui/format_args_unfixable.rs:151:5
|
LL | usr_println!(true, "error: {}", format!(r#"boom at "{}""#, Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -229,7 +229,7 @@ LL | usr_println!(true, "error: {}", format!(r#"boom at "{}""#, Location::ca
= help: or consider changing `format!` to `format_args!`

error: `format!` in `usr_println!` args
--> tests/ui/format_args_unfixable.rs:148:5
--> tests/ui/format_args_unfixable.rs:153:5
|
LL | usr_println!(true, "error: {}", format!("boom at {} {0}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
Loading

0 comments on commit d940211

Please sign in to comment.