mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-10 15:14:29 +00:00
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:
436675b477/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
This commit is contained in:
commit
0b441d5ac5
3 changed files with 26 additions and 2 deletions
|
@ -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
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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() {}
|
||||
|
|
Loading…
Reference in a new issue