Skip to content

Commit 0c767ea

Browse files
authored
Merge branch 'master' into master
2 parents 7cfa9ff + 6553b98 commit 0c767ea

12 files changed

+197
-3
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3822,6 +3822,7 @@ Released 2018-09-13
38223822
[`unused_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect
38233823
[`unused_io_amount`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_io_amount
38243824
[`unused_label`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_label
3825+
[`unused_rounding`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_rounding
38253826
[`unused_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_self
38263827
[`unused_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit
38273828
[`unusual_byte_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unusual_byte_groupings

clippy_lints/src/lib.register_lints.rs

+1
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ store.register_lints(&[
547547
unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME,
548548
unused_async::UNUSED_ASYNC,
549549
unused_io_amount::UNUSED_IO_AMOUNT,
550+
unused_rounding::UNUSED_ROUNDING,
550551
unused_self::UNUSED_SELF,
551552
unused_unit::UNUSED_UNIT,
552553
unwrap::PANICKING_UNWRAP,

clippy_lints/src/lib.register_nursery.rs

+1
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,6 @@ store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
3232
LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS),
3333
LintId::of(transmute::TRANSMUTE_UNDEFINED_REPR),
3434
LintId::of(transmute::USELESS_TRANSMUTE),
35+
LintId::of(unused_rounding::UNUSED_ROUNDING),
3536
LintId::of(use_self::USE_SELF),
3637
])

clippy_lints/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ mod unnested_or_patterns;
403403
mod unsafe_removed_from_name;
404404
mod unused_async;
405405
mod unused_io_amount;
406+
mod unused_rounding;
406407
mod unused_self;
407408
mod unused_unit;
408409
mod unwrap;
@@ -907,6 +908,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
907908
store.register_late_pass(|| Box::new(rc_clone_in_vec_init::RcCloneInVecInit));
908909
store.register_early_pass(|| Box::new(duplicate_mod::DuplicateMod::default()));
909910
store.register_late_pass(|| Box::new(get_first::GetFirst));
911+
store.register_early_pass(|| Box::new(unused_rounding::UnusedRounding));
910912
store.register_late_pass(|| Box::new(path_from_format::PathFromFormat));
911913
// add lints here, do not remove this comment, it's used in `new_lint`
912914
}

clippy_lints/src/match_str_case_mismatch.rs

-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ declare_clippy_lint! {
2121
/// ### Example
2222
/// ```rust
2323
/// # let text = "Foo";
24-
///
2524
/// match &*text.to_ascii_lowercase() {
2625
/// "foo" => {},
2726
/// "Bar" => {},
@@ -31,7 +30,6 @@ declare_clippy_lint! {
3130
/// Use instead:
3231
/// ```rust
3332
/// # let text = "Foo";
34-
///
3533
/// match &*text.to_ascii_lowercase() {
3634
/// "foo" => {},
3735
/// "bar" => {},

clippy_lints/src/unused_rounding.rs

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use rustc_ast::ast::{Expr, ExprKind, LitFloatType, LitKind};
3+
use rustc_errors::Applicability;
4+
use rustc_lint::{EarlyContext, EarlyLintPass};
5+
use rustc_session::{declare_lint_pass, declare_tool_lint};
6+
7+
declare_clippy_lint! {
8+
/// ### What it does
9+
///
10+
/// Detects cases where a whole-number literal float is being rounded, using
11+
/// the `floor`, `ceil`, or `round` methods.
12+
///
13+
/// ### Why is this bad?
14+
///
15+
/// This is unnecessary and confusing to the reader. Doing this is probably a mistake.
16+
///
17+
/// ### Example
18+
/// ```rust
19+
/// let x = 1f32.ceil();
20+
/// ```
21+
/// Use instead:
22+
/// ```rust
23+
/// let x = 1f32;
24+
/// ```
25+
#[clippy::version = "1.62.0"]
26+
pub UNUSED_ROUNDING,
27+
nursery,
28+
"Uselessly rounding a whole number floating-point literal"
29+
}
30+
declare_lint_pass!(UnusedRounding => [UNUSED_ROUNDING]);
31+
32+
fn is_useless_rounding(expr: &Expr) -> Option<(&str, String)> {
33+
if let ExprKind::MethodCall(name_ident, args, _) = &expr.kind
34+
&& let method_name = name_ident.ident.name.as_str()
35+
&& (method_name == "ceil" || method_name == "round" || method_name == "floor")
36+
&& !args.is_empty()
37+
&& let ExprKind::Lit(spanned) = &args[0].kind
38+
&& let LitKind::Float(symbol, ty) = spanned.kind {
39+
let f = symbol.as_str().parse::<f64>().unwrap();
40+
let f_str = symbol.to_string() + if let LitFloatType::Suffixed(ty) = ty {
41+
ty.name_str()
42+
} else {
43+
""
44+
};
45+
if f.fract() == 0.0 {
46+
Some((method_name, f_str))
47+
} else {
48+
None
49+
}
50+
} else {
51+
None
52+
}
53+
}
54+
55+
impl EarlyLintPass for UnusedRounding {
56+
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
57+
if let Some((method_name, float)) = is_useless_rounding(expr) {
58+
span_lint_and_sugg(
59+
cx,
60+
UNUSED_ROUNDING,
61+
expr.span,
62+
&format!("used the `{}` method with a whole number float", method_name),
63+
&format!("remove the `{}` method call", method_name),
64+
float,
65+
Applicability::MachineApplicable,
66+
);
67+
}
68+
}
69+
}

clippy_utils/src/lib.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -1916,7 +1916,17 @@ pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
19161916
..
19171917
},
19181918
..,
1919-
) => cx.typeck_results().qpath_res(qpath, *path_hir_id).opt_def_id(),
1919+
) => {
1920+
// Only return Fn-like DefIds, not the DefIds of statics/consts/etc that contain or
1921+
// deref to fn pointers, dyn Fn, impl Fn - #8850
1922+
if let Res::Def(DefKind::Fn | DefKind::Ctor(..) | DefKind::AssocFn, id) =
1923+
cx.typeck_results().qpath_res(qpath, *path_hir_id)
1924+
{
1925+
Some(id)
1926+
} else {
1927+
None
1928+
}
1929+
},
19201930
_ => None,
19211931
}
19221932
}

tests/ui/crashes/ice-8850.rs

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
fn fn_pointer_static() -> usize {
2+
static FN: fn() -> usize = || 1;
3+
let res = FN() + 1;
4+
res
5+
}
6+
7+
fn fn_pointer_const() -> usize {
8+
const FN: fn() -> usize = || 1;
9+
let res = FN() + 1;
10+
res
11+
}
12+
13+
fn deref_to_dyn_fn() -> usize {
14+
struct Derefs;
15+
impl std::ops::Deref for Derefs {
16+
type Target = dyn Fn() -> usize;
17+
18+
fn deref(&self) -> &Self::Target {
19+
&|| 2
20+
}
21+
}
22+
static FN: Derefs = Derefs;
23+
let res = FN() + 1;
24+
res
25+
}
26+
27+
fn main() {}

tests/ui/crashes/ice-8850.stderr

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
error: returning the result of a `let` binding from a block
2+
--> $DIR/ice-8850.rs:4:5
3+
|
4+
LL | let res = FN() + 1;
5+
| ------------------- unnecessary `let` binding
6+
LL | res
7+
| ^^^
8+
|
9+
= note: `-D clippy::let-and-return` implied by `-D warnings`
10+
help: return the expression directly
11+
|
12+
LL ~
13+
LL ~ FN() + 1
14+
|
15+
16+
error: returning the result of a `let` binding from a block
17+
--> $DIR/ice-8850.rs:10:5
18+
|
19+
LL | let res = FN() + 1;
20+
| ------------------- unnecessary `let` binding
21+
LL | res
22+
| ^^^
23+
|
24+
help: return the expression directly
25+
|
26+
LL ~
27+
LL ~ FN() + 1
28+
|
29+
30+
error: returning the result of a `let` binding from a block
31+
--> $DIR/ice-8850.rs:24:5
32+
|
33+
LL | let res = FN() + 1;
34+
| ------------------- unnecessary `let` binding
35+
LL | res
36+
| ^^^
37+
|
38+
help: return the expression directly
39+
|
40+
LL ~
41+
LL ~ FN() + 1
42+
|
43+
44+
error: aborting due to 3 previous errors
45+

tests/ui/unused_rounding.fixed

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// run-rustfix
2+
#![warn(clippy::unused_rounding)]
3+
4+
fn main() {
5+
let _ = 1f32;
6+
let _ = 1.0f64;
7+
let _ = 1.00f32;
8+
let _ = 2e-54f64.floor();
9+
}

tests/ui/unused_rounding.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// run-rustfix
2+
#![warn(clippy::unused_rounding)]
3+
4+
fn main() {
5+
let _ = 1f32.ceil();
6+
let _ = 1.0f64.floor();
7+
let _ = 1.00f32.round();
8+
let _ = 2e-54f64.floor();
9+
}

tests/ui/unused_rounding.stderr

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error: used the `ceil` method with a whole number float
2+
--> $DIR/unused_rounding.rs:5:13
3+
|
4+
LL | let _ = 1f32.ceil();
5+
| ^^^^^^^^^^^ help: remove the `ceil` method call: `1f32`
6+
|
7+
= note: `-D clippy::unused-rounding` implied by `-D warnings`
8+
9+
error: used the `floor` method with a whole number float
10+
--> $DIR/unused_rounding.rs:6:13
11+
|
12+
LL | let _ = 1.0f64.floor();
13+
| ^^^^^^^^^^^^^^ help: remove the `floor` method call: `1.0f64`
14+
15+
error: used the `round` method with a whole number float
16+
--> $DIR/unused_rounding.rs:7:13
17+
|
18+
LL | let _ = 1.00f32.round();
19+
| ^^^^^^^^^^^^^^^ help: remove the `round` method call: `1.00f32`
20+
21+
error: aborting due to 3 previous errors
22+

0 commit comments

Comments
 (0)