diff options
| author | bors <bors@rust-lang.org> | 2024-06-07 09:33:48 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-06-07 09:33:48 +0000 |
| commit | 0b441d5ac5934eecb4254f71a8557cf9cb6b882e (patch) | |
| tree | 36422fee03327235a331a55194dcf2ca92e7bd8b | |
| parent | d9ae9367ba7814a380b6501c3ca67dadd3d72641 (diff) | |
| parent | 25d40c9f6b09b4decd17c564c037e1f8de9859b2 (diff) | |
Auto merge of #12877 - y21:const_host_ice, r=dswij
Handle const effects inherited from parent correctly in `type_certainty` This fixes a (debug) ICE in `type_certainty` that happened in the [k256 crate]. (I'm sure you can also specifically construct an edge test case that will run into type_certainty false positives visible outside of debug builds from this bug) <details> <summary>Minimal ICE repro</summary> ```rs use std::ops::Add; Add::add(1_i32, 1).add(i32::MIN); ``` </details> The subtraction here overflowed: https://github.com/rust-lang/rust-clippy/blob/436675b4772049a0ff535bd46d944689c90ed750/clippy_utils/src/ty/type_certainty/mod.rs#L209 ... when we have something like `Add::add` where `add` fn has 0 generic params but the `host_effect_index` is `Some(2)` (inherited from the parent generics, the const trait `Add`), and we end up executing `0 - 1`. (Even if the own generics weren't empty and we didn't overflow, this would still be wrong because it would assume that a trait method with 1 generic parameter didn't have any generics). So, *only* exclude the "host" generic parameter if it's actually bound by the own generics changelog: none [k256 crate]: https://github.com/RustCrypto/elliptic-curves/tree/master/k256
| -rw-r--r-- | clippy_utils/src/ty/type_certainty/mod.rs | 14 | ||||
| -rw-r--r-- | tests/ui/or_fun_call.fixed | 7 | ||||
| -rw-r--r-- | tests/ui/or_fun_call.rs | 7 |
3 files changed, 26 insertions, 2 deletions
diff --git a/clippy_utils/src/ty/type_certainty/mod.rs b/clippy_utils/src/ty/type_certainty/mod.rs index 80219303450..cba61c841ef 100644 --- a/clippy_utils/src/ty/type_certainty/mod.rs +++ b/clippy_utils/src/ty/type_certainty/mod.rs @@ -206,8 +206,18 @@ fn path_segment_certainty( // Checking `res_generics_def_id(..)` before calling `generics_of` avoids an ICE. if cx.tcx.res_generics_def_id(path_segment.res).is_some() { let generics = cx.tcx.generics_of(def_id); - let count = generics.own_params.len() - usize::from(generics.host_effect_index.is_some()); - let lhs = if (parent_certainty.is_certain() || generics.parent_count == 0) && count == 0 { + + let own_count = generics.own_params.len() + - usize::from(generics.host_effect_index.is_some_and(|index| { + // Check that the host index actually belongs to this resolution. + // E.g. for `Add::add`, host_effect_index is `Some(2)`, but it's part of the parent `Add` + // trait's generics. + // Add params: [Self#0, Rhs#1, host#2] parent_count=0, count=3 + // Add::add params: [] parent_count=3, count=3 + // (3..3).contains(&host_effect_index) => false + (generics.parent_count..generics.count()).contains(&index) + })); + let lhs = if (parent_certainty.is_certain() || generics.parent_count == 0) && own_count == 0 { Certainty::Certain(None) } else { Certainty::Uncertain diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed index e7ba54864ab..7657ef470c5 100644 --- a/tests/ui/or_fun_call.fixed +++ b/tests/ui/or_fun_call.fixed @@ -311,4 +311,11 @@ mod lazy { } } +fn host_effect() { + // #12877 - make sure we don't ICE in type_certainty + use std::ops::Add; + + Add::<i32>::add(1, 1).add(i32::MIN); +} + fn main() {} diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs index 196632133d5..97cf496d3ac 100644 --- a/tests/ui/or_fun_call.rs +++ b/tests/ui/or_fun_call.rs @@ -311,4 +311,11 @@ mod lazy { } } +fn host_effect() { + // #12877 - make sure we don't ICE in type_certainty + use std::ops::Add; + + Add::<i32>::add(1, 1).add(i32::MIN); +} + fn main() {} |
