diff options
| author | bors <bors@rust-lang.org> | 2024-04-04 22:17:50 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-04-04 22:17:50 +0000 |
| commit | 8253040b3f991bd87ad3b1d5ce175bd3ebe599f4 (patch) | |
| tree | f269a55a9ca6d2a89a9efc27b352404be118bd40 | |
| parent | a73e751d1939fdf5b14df28f53704616e63963f3 (diff) | |
| parent | 9f5d31ef862489ea87bf3e52812d05b1a700de47 (diff) | |
| download | rust-8253040b3f991bd87ad3b1d5ce175bd3ebe599f4.tar.gz rust-8253040b3f991bd87ad3b1d5ce175bd3ebe599f4.zip | |
Auto merge of #12591 - y21:issue12585, r=Jarcho
type certainty: clear `DefId` when an expression's type changes to non-adt Fixes #12585 The root cause of the ICE in the linked issue was in the expression `one.x`, in the array literal. The type of `one` is the `One` struct: an adt with a DefId, so its certainty is `Certain(def_id_of_one)`. However, the field access `.x` can then change the type (to `i32` here) and that should update that `DefId` accordingly. It does do that correctly when `one.x` would be another adt with a DefId: https://github.com/rust-lang/rust-clippy/blob/97ba291d5aa026353ad93e48cf00e06f08c73830/clippy_utils/src/ty/type_certainty/mod.rs#L90-L91 but when it *isn't* an adt and there is no def id (which is the case in the linked issue: `one.x` is an i32), it keeps the `DefId` of `One`, even though that's the wrong type (which would then lead to a contradiction later when joining `Certainty`s): https://github.com/rust-lang/rust-clippy/blob/97ba291d5aa026353ad93e48cf00e06f08c73830/clippy_utils/src/ty/type_certainty/mod.rs#L92-L93 In particular, in the linked issue, `from_array([one.x, two.x])` would try to join the `Certainty` of the two array elements, which *should* have been `[Certain(None), Certain(None)]`, because `i32`s have no `DefId`, but instead it was `[Certain(One), Certain(Two)]`, because the DefId wasn't cleared from when it was visiting `one` and `two`. This is the "contradiction" that could be seen in the ICE message ... so this changes it to clear the `DefId` when it isn't an adt. cc `@smoelius` you implemented this initially in #11135, does this change make sense to you? changelog: none
| -rw-r--r-- | clippy_utils/src/ty/type_certainty/mod.rs | 2 | ||||
| -rw-r--r-- | tests/ui/crashes/ice-12585.rs | 26 |
2 files changed, 27 insertions, 1 deletions
diff --git a/clippy_utils/src/ty/type_certainty/mod.rs b/clippy_utils/src/ty/type_certainty/mod.rs index 762830ffd78..2241494b484 100644 --- a/clippy_utils/src/ty/type_certainty/mod.rs +++ b/clippy_utils/src/ty/type_certainty/mod.rs @@ -90,7 +90,7 @@ fn expr_type_certainty(cx: &LateContext<'_>, expr: &Expr<'_>) -> Certainty { if let Some(def_id) = adt_def_id(expr_ty) { certainty.with_def_id(def_id) } else { - certainty + certainty.clear_def_id() } } diff --git a/tests/ui/crashes/ice-12585.rs b/tests/ui/crashes/ice-12585.rs new file mode 100644 index 00000000000..7928115c0a9 --- /dev/null +++ b/tests/ui/crashes/ice-12585.rs @@ -0,0 +1,26 @@ +#![allow(clippy::unit_arg)] + +struct One { + x: i32, +} +struct Two { + x: i32, +} + +struct Product {} + +impl Product { + pub fn a_method(self, _: ()) {} +} + +fn from_array(_: [i32; 2]) -> Product { + todo!() +} + +pub fn main() { + let one = One { x: 1 }; + let two = Two { x: 2 }; + + let product = from_array([one.x, two.x]); + product.a_method(<()>::default()); +} |
