Skip to content

Commit 6472939

Browse files
Implemented majority of from_str_radix_10
1 parent b80ac2a commit 6472939

File tree

3 files changed

+86
-6
lines changed

3 files changed

+86
-6
lines changed

clippy_lints/src/from_str_radix_10.rs

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
use rustc_lint::{EarlyLintPass, EarlyContext};
1+
use rustc_lint::{LateLintPass, LateContext};
22
use rustc_session::{declare_lint_pass, declare_tool_lint};
3-
use rustc_ast::ast::*;
3+
use rustc_hir::*;
4+
use rustc_errors::Applicability;
5+
use if_chain::if_chain;
6+
7+
use crate::utils::span_lint_and_sugg;
48

59
declare_clippy_lint! {
610
/// **What it does:**
@@ -26,9 +30,56 @@ declare_clippy_lint! {
2630
/// ```
2731
pub FROM_STR_RADIX_10,
2832
style,
29-
"default lint description"
33+
"from_str_radix with radix 10"
3034
}
3135

3236
declare_lint_pass!(FromStrRadix10 => [FROM_STR_RADIX_10]);
3337

34-
impl EarlyLintPass for FromStrRadix10 {}
38+
impl LateLintPass<'tcx> for FromStrRadix10 {
39+
fn check_expr(&mut self, cx: &LateContext<'tcx>, exp: &Expr<'tcx>) {
40+
if_chain! {
41+
if let ExprKind::Call(maybe_path, arguments) = &exp.kind;
42+
if let ExprKind::Path(qpath) = &maybe_path.kind;
43+
if let QPath::TypeRelative(ty, pathseg) = &qpath;
44+
45+
// check if the first part of the path is some integer primitive
46+
if let TyKind::Path(ty_qpath) = &ty.kind;
47+
let ty_res = cx.qpath_res(ty_qpath, ty.hir_id);
48+
if let def::Res::PrimTy(prim_ty) = ty_res;
49+
if is_primitive_integer_ty(prim_ty);
50+
51+
// check if the second part of the path indeed calls the associated
52+
// function `from_str_radix`
53+
if pathseg.ident.name.as_str() == "from_str_radix";
54+
55+
// check if the second argument resolves to a constant `10`
56+
if arguments.len() == 2;
57+
if is_constant_10(&arguments[1]);
58+
59+
then {
60+
span_lint_and_sugg(
61+
cx,
62+
FROM_STR_RADIX_10,
63+
exp.span,
64+
"This call to `from_str_radix` can be shortened to a call to str::parse",
65+
"try",
66+
format!("TODO"),
67+
Applicability::MachineApplicable
68+
);
69+
}
70+
}
71+
}
72+
}
73+
74+
fn is_primitive_integer_ty(ty: PrimTy) -> bool {
75+
match ty {
76+
PrimTy::Int(_) => true,
77+
PrimTy::Uint(_) => true,
78+
_ => false
79+
}
80+
}
81+
82+
fn is_constant_10<'tcx>(expr: &Expr<'tcx>) -> bool {
83+
// TODO
84+
true
85+
}

clippy_lints/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,6 +1258,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
12581258
store.register_late_pass(move || box types::PtrAsPtr::new(msrv));
12591259
store.register_late_pass(|| box case_sensitive_file_extension_comparisons::CaseSensitiveFileExtensionComparisons);
12601260
store.register_late_pass(|| box redundant_slicing::RedundantSlicing);
1261+
store.register_late_pass(|| box from_str_radix_10::FromStrRadix10);
12611262

12621263
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
12631264
LintId::of(&arithmetic::FLOAT_ARITHMETIC),

tests/ui/from_str_radix_10.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,33 @@
11
#![warn(clippy::from_str_radix_10)]
22

3-
fn main() {
4-
// test code goes here
3+
mod some_mod {
4+
// fake function that shouldn't trigger the lint
5+
pub fn from_str_radix(_: &str, _: u32) -> Result<(), std::num::ParseIntError> {
6+
unimplemented!()
7+
}
58
}
9+
10+
// fake function that shouldn't trigger the lint
11+
fn from_str_radix(_: &str, _: u32) -> Result<(), std::num::ParseIntError> {
12+
unimplemented!()
13+
}
14+
15+
fn main() -> Result<(), Box<dyn std::error::Error>> {
16+
// all of these should trigger the lint
17+
u32::from_str_radix("30", 10)?;
18+
i64::from_str_radix("24", 10)?;
19+
isize::from_str_radix("100", 10)?;
20+
u8::from_str_radix("7", 10)?;
21+
22+
// none of these should trigger the lint
23+
u16::from_str_radix("20", 3)?;
24+
i32::from_str_radix("45", 12)?;
25+
usize::from_str_radix("10", 16)?;
26+
i128::from_str_radix("10", 13)?;
27+
some_mod::from_str_radix("50", 10)?;
28+
some_mod::from_str_radix("50", 6)?;
29+
from_str_radix("50", 10)?;
30+
from_str_radix("50", 6)?;
31+
32+
Ok(())
33+
}

0 commit comments

Comments
 (0)