-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Description
Summary
There are a number of cases where the lint default_numeric_fallback
is emitted, but no numeric fallback actually occurs due to type inference. I want to use this lint on my projects, but it causes far too many false positives.
Currently, the lint is emitted whenever a numeric literal contains no type suffix, is of the type i32
or f64
, and is not a part of a large set of hardcoded cases where type inferences in known to occur. I believe that due to the complexity of type inference in Rust, the lint should instead directly check if rustc
is actually doing numeric fallback.
I would like to help work on a PR implementing these changes, but the private rustc
crates currently don't seem to provide any sort of interface to check if numeric fallback occurred. I think the ideal implementation should hook into this function and I could think of a few approaches, but I'm not sure what's best. This would also require updating rustc
and then clippy
, and I'm unsure what the process for that is like.
Furthermore, in my opinion, looking at RFC0212 as mentioned in the lint description, there are still a few common cases where the type fallen back to does not matter at all, and I think it's worth whitelisting those specific cases.
(0..100).map(|_| {})
: This include all cases where a range in used as an iterator, but all values out of the iterator is discarded. This is often used to iterate a set number of times, where the type doesn't matter.number << 8
: While fallback does occur here,<<
and>>
are implemented on all integer types with identical behavior.10 > 0
within a macro: I only include this because it was mentioned here. I have not yet ran into this case in my code.
Lint Name
default_numeric_fallback
Reproducer
I tried this code:
#![warn(clippy::default_numeric_fallback)]
fn id_f64(x: f64) -> f64 {
x
}
struct A<T>(pub T);
fn main() {
// inference due to binary operations
let mut a: f64;
a = 1.;
a *= 2.;
let b = 5i32;
let _ = a > 2. || b == 3;
let _ = 2. / 1f64;
// inference due to if and match
let x = 10f64;
let _ = if true { x } else { 10. };
let _ = match 3i32 {
3 => x,
_ => 10.,
};
let _ = matches!(5i32, 1..=10);
// inference due to assignment
let t = (4., 5);
let _: (f64, i32) = t;
let _: A<f64> = A(1.);
// inference due to functions
let z = 10.;
let _ = id_f64(z) == 10.;
let mut o = None::<f64>;
let _ = &mut o;
let _ = o.unwrap_or(1.);
let mut v: Vec<i32> = vec![];
let _ = &mut v;
v.push(1);
// inference due to array
let a = [1., 2.];
let _: f64 = *a.first().unwrap();
// fallback doesn't have any real effect
let _ = 1u32 << 8;
for _ in 0..100 {}
}
I saw this happen:
There is a warning on every single unsuffixed numeric literal.
I expected to see this happen:
There should be no warning at all.
Version
rustc 1.81.0-nightly (6868c831a 2024-06-30)
binary: rustc
commit-hash: 6868c831a1eb45c5150ff623cef5e42a8b8946d0
commit-date: 2024-06-30
host: x86_64-unknown-linux-gnu
release: 1.81.0-nightly
LLVM version: 18.1.7
Additional Labels
No response