@@ -1192,19 +1192,35 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11921192 } ;
11931193 let bounds = tcx. item_bounds ( def_id) . subst ( tcx, substs) ;
11941194
1195+ // The bounds returned by `item_bounds` may contain duplicates after
1196+ // normalization, so try to deduplicate when possible to avoid
1197+ // unnecessary ambiguity.
1198+ let mut distinct_normalized_bounds = FxHashSet :: default ( ) ;
1199+
11951200 let matching_bounds = bounds
11961201 . iter ( )
11971202 . enumerate ( )
11981203 . filter_map ( |( idx, bound) | {
11991204 if let ty:: PredicateAtom :: Trait ( pred, _) = bound. skip_binders ( ) {
12001205 let bound = ty:: Binder :: bind ( pred. trait_ref ) ;
12011206 if self . infcx . probe ( |_| {
1202- self . match_projection (
1207+ if let Ok ( normalized_trait ) = self . match_projection (
12031208 obligation,
12041209 bound,
12051210 placeholder_trait_predicate. trait_ref ,
1206- )
1207- . is_ok ( )
1211+ ) {
1212+ match normalized_trait {
1213+ None => true ,
1214+ Some ( normalized_trait)
1215+ if distinct_normalized_bounds. insert ( normalized_trait) =>
1216+ {
1217+ true
1218+ }
1219+ _ => false ,
1220+ }
1221+ } else {
1222+ false
1223+ }
12081224 } ) {
12091225 return Some ( idx) ;
12101226 }
@@ -1221,34 +1237,41 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12211237 matching_bounds
12221238 }
12231239
1240+ /// Equates the trait in `obligation` with trait bound. If the two traits
1241+ /// can be equated and the normalized trait bound doesn't contain inference
1242+ /// variables or placeholders, the normalized bound is returned.
12241243 fn match_projection (
12251244 & mut self ,
12261245 obligation : & TraitObligation < ' tcx > ,
12271246 trait_bound : ty:: PolyTraitRef < ' tcx > ,
12281247 placeholder_trait_ref : ty:: TraitRef < ' tcx > ,
1229- ) -> Result < Vec < PredicateObligation < ' tcx > > , ( ) > {
1248+ ) -> Result < Option < ty :: PolyTraitRef < ' tcx > > , ( ) > {
12301249 debug_assert ! ( !placeholder_trait_ref. has_escaping_bound_vars( ) ) ;
12311250 if placeholder_trait_ref. def_id != trait_bound. def_id ( ) {
12321251 // Avoid unnecessary normalization
12331252 return Err ( ( ) ) ;
12341253 }
12351254
1236- let Normalized { value : trait_bound, obligations : mut nested_obligations } =
1237- ensure_sufficient_stack ( || {
1238- project:: normalize_with_depth (
1239- self ,
1240- obligation. param_env ,
1241- obligation. cause . clone ( ) ,
1242- obligation. recursion_depth + 1 ,
1243- & trait_bound,
1244- )
1245- } ) ;
1255+ let Normalized { value : trait_bound, obligations : _ } = ensure_sufficient_stack ( || {
1256+ project:: normalize_with_depth (
1257+ self ,
1258+ obligation. param_env ,
1259+ obligation. cause . clone ( ) ,
1260+ obligation. recursion_depth + 1 ,
1261+ & trait_bound,
1262+ )
1263+ } ) ;
12461264 self . infcx
12471265 . at ( & obligation. cause , obligation. param_env )
12481266 . sup ( ty:: Binder :: dummy ( placeholder_trait_ref) , trait_bound)
1249- . map ( |InferOk { obligations, .. } | {
1250- nested_obligations. extend ( obligations) ;
1251- nested_obligations
1267+ . map ( |InferOk { obligations : _, value : ( ) } | {
1268+ // This method is called within a probe, so we can't have
1269+ // inference variables and placeholders escape.
1270+ if !trait_bound. needs_infer ( ) && !trait_bound. has_placeholders ( ) {
1271+ Some ( trait_bound)
1272+ } else {
1273+ None
1274+ }
12521275 } )
12531276 . map_err ( |_| ( ) )
12541277 }
0 commit comments