Skip to content

Commit 3d881e1

Browse files
authored
Prevent ICE in case of a bound constraint on generic argument (rust-lang#13722)
Fix rust-lang#13706 changelog: [`trait_duplication_in_bounds`]: fix ICE on duplicate type or constant bound
2 parents d070402 + 9fd8e99 commit 3d881e1

File tree

3 files changed

+38
-7
lines changed

3 files changed

+38
-7
lines changed

clippy_utils/src/hir_utils.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -603,11 +603,7 @@ impl HirEqInterExpr<'_, '_, '_> {
603603
}
604604

605605
fn eq_assoc_type_binding(&mut self, left: &AssocItemConstraint<'_>, right: &AssocItemConstraint<'_>) -> bool {
606-
left.ident.name == right.ident.name
607-
&& self.eq_ty(
608-
left.ty().expect("expected assoc type binding"),
609-
right.ty().expect("expected assoc type binding"),
610-
)
606+
left.ident.name == right.ident.name && both_some_and(left.ty(), right.ty(), |l, r| self.eq_ty(l, r))
611607
}
612608

613609
fn check_ctxt(&mut self, left: SyntaxContext, right: SyntaxContext) -> bool {
@@ -727,6 +723,11 @@ pub fn both<X>(l: Option<&X>, r: Option<&X>, mut eq_fn: impl FnMut(&X, &X) -> bo
727723
.map_or_else(|| r.is_none(), |x| r.as_ref().is_some_and(|y| eq_fn(x, y)))
728724
}
729725

726+
/// Checks if the two `Option`s are both `Some` and pass the predicate function.
727+
pub fn both_some_and<X, Y>(l: Option<X>, r: Option<Y>, mut pred: impl FnMut(X, Y) -> bool) -> bool {
728+
l.is_some_and(|l| r.is_some_and(|r| pred(l, r)))
729+
}
730+
730731
/// Checks if two slices are equal as per `eq_fn`.
731732
pub fn over<X>(left: &[X], right: &[X], mut eq_fn: impl FnMut(&X, &X) -> bool) -> bool {
732733
left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y))

tests/ui/trait_duplication_in_bounds.fixed

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![deny(clippy::trait_duplication_in_bounds)]
22
#![allow(unused)]
3-
#![feature(const_trait_impl)]
3+
#![feature(associated_const_equality, const_trait_impl)]
44

55
use std::any::Any;
66

@@ -179,3 +179,18 @@ fn main() {
179179
let _x: fn(_) = f::<()>;
180180
let _x: fn(_) = f::<i32>;
181181
}
182+
183+
// #13706
184+
fn assoc_tys_bounds<T>()
185+
where
186+
T: Iterator<Item: Clone> + Iterator<Item: Clone>,
187+
{
188+
}
189+
trait AssocConstTrait {
190+
const ASSOC: usize;
191+
}
192+
fn assoc_const_args<T>()
193+
where
194+
T: AssocConstTrait<ASSOC = 0> + AssocConstTrait<ASSOC = 0>,
195+
{
196+
}

tests/ui/trait_duplication_in_bounds.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![deny(clippy::trait_duplication_in_bounds)]
22
#![allow(unused)]
3-
#![feature(const_trait_impl)]
3+
#![feature(associated_const_equality, const_trait_impl)]
44

55
use std::any::Any;
66

@@ -179,3 +179,18 @@ fn main() {
179179
let _x: fn(_) = f::<()>;
180180
let _x: fn(_) = f::<i32>;
181181
}
182+
183+
// #13706
184+
fn assoc_tys_bounds<T>()
185+
where
186+
T: Iterator<Item: Clone> + Iterator<Item: Clone>,
187+
{
188+
}
189+
trait AssocConstTrait {
190+
const ASSOC: usize;
191+
}
192+
fn assoc_const_args<T>()
193+
where
194+
T: AssocConstTrait<ASSOC = 0> + AssocConstTrait<ASSOC = 0>,
195+
{
196+
}

0 commit comments

Comments
 (0)