ty::GenericParamDefKind::Const { .. } => None,
}).collect::<Vec<GenericParamDef>>();
- // (param index, def id of trait) -> (name, type)
- let mut impl_trait_proj = FxHashMap::<(u32, DefId), Vec<(String, Type)>>::default();
+ // param index -> [(DefId of trait, associated type name, type)]
+ let mut impl_trait_proj =
+ FxHashMap::<u32, Vec<(DefId, String, Ty<'tcx>)>>::default();
let mut where_predicates = preds.predicates.iter()
.flat_map(|(p, _)| {
+ let mut projection = None;
let param_idx = (|| {
if let Some(trait_ref) = p.to_opt_poly_trait_ref() {
if let ty::Param(param) = trait_ref.self_ty().sty {
if let ty::Param(param) = outlives.skip_binder().0.sty {
return Some(param.index);
}
- } else if let ty::Predicate::Projection(proj) = p {
- if let ty::Param(param) = proj.skip_binder().projection_ty.self_ty().sty {
+ } else if let ty::Predicate::Projection(p) = p {
+ if let ty::Param(param) = p.skip_binder().projection_ty.self_ty().sty {
+ projection = Some(p);
return Some(param.index);
}
}
.filter(|b| !b.is_sized_bound(cx))
);
- let proj = match &p {
- WherePredicate::EqPredicate { lhs, rhs } => Some((lhs, rhs))
- .and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs))),
- _ => None,
- };
- if let Some(((_, trait_did, name), rhs)) = proj {
+ let proj = projection
+ .map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().ty));
+ if let Some(((_, trait_did, name), rhs)) =
+ proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs)))
+ {
impl_trait_proj
- .entry((param_idx, trait_did))
+ .entry(param_idx)
.or_default()
- .push((name.to_string(), rhs.clone()));
+ .push((trait_did, name.to_string(), rhs));
}
return None;
})
.collect::<Vec<_>>();
- for ((param_idx, trait_did), bounds) in impl_trait_proj {
- for (name, rhs) in bounds {
- simplify::merge_bounds(
- cx,
- impl_trait.get_mut(¶m_idx.into()).unwrap(),
- trait_did,
- &name,
- &rhs,
- );
- }
- }
-
// Move `TraitPredicate`s to the front.
for (_, bounds) in impl_trait.iter_mut() {
bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b {
});
}
- cx.impl_trait_bounds.borrow_mut().extend(impl_trait);
+ for (param, mut bounds) in impl_trait {
+ if let crate::core::ImplTraitParam::ParamIndex(idx) = param {
+ if let Some(proj) = impl_trait_proj.remove(&idx) {
+ for (trait_did, name, rhs) in proj {
+ simplify::merge_bounds(
+ cx,
+ &mut bounds,
+ trait_did,
+ &name,
+ &rhs.clean(cx),
+ );
+ }
+ }
+ } else {
+ unreachable!();
+ }
+
+ cx.impl_trait_bounds.borrow_mut().insert(param, bounds);
+ }
// Type parameters and have a Sized bound by default unless removed with
// ?Sized. Scan through the predicates and mark any type parameter with
pub use impl_trait_aux::func;
// @has impl_trait/fn.func2.html
+// @has - '//pre[@class="rust fn"]' "func2<T>("
// @has - '//pre[@class="rust fn"]' "_x: impl Deref<Target = Option<T>> + Iterator<Item = T>,"
// @has - '//pre[@class="rust fn"]' "_y: impl Iterator<Item = u8>)"
// @!has - '//pre[@class="rust fn"]' 'where'
pub use impl_trait_aux::func2;
+// @has impl_trait/fn.func3.html
+// @has - '//pre[@class="rust fn"]' "func3(_x: impl Clone + Iterator<Item = impl Iterator<Item = u8>>)"
+// @!has - '//pre[@class="rust fn"]' 'where'
+pub use impl_trait_aux::func3;
+
// @has impl_trait/struct.Foo.html
// @has - '//code[@id="method.v"]' "pub fn method<'a>(_x: impl Clone + Into<Vec<u8>> + 'a)"
// @!has - '//code[@id="method.v"]' 'where'