@@ -19,6 +19,7 @@ use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey};
1919use crate :: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
2020use crate :: infer:: { InferCtxt , InferOk , LateBoundRegionConversionTime } ;
2121use crate :: traits:: error_reporting:: InferCtxtExt as _;
22+ use crate :: traits:: select:: ProjectionMatchesProjection ;
2223use rustc_data_structures:: sso:: SsoHashSet ;
2324use rustc_data_structures:: stack:: ensure_sufficient_stack;
2425use rustc_errors:: ErrorReported ;
@@ -1075,16 +1076,6 @@ fn project<'cx, 'tcx>(
10751076 return Ok ( Projected :: Progress ( Progress :: error ( selcx. tcx ( ) ) ) ) ;
10761077 }
10771078
1078- // If the obligation contains any inference types or consts in associated
1079- // type substs, then we don't assemble any candidates.
1080- // This isn't really correct, but otherwise we can end up in a case where
1081- // we constrain inference variables by selecting a single predicate, when
1082- // we need to stay general. See issue #91762.
1083- let ( _, predicate_own_substs) = obligation. predicate . trait_ref_and_own_substs ( selcx. tcx ( ) ) ;
1084- if predicate_own_substs. iter ( ) . any ( |g| g. has_infer_types_or_consts ( ) ) {
1085- return Err ( ProjectionError :: TooManyCandidates ) ;
1086- }
1087-
10881079 let mut candidates = ProjectionCandidateSet :: None ;
10891080
10901081 // Make sure that the following procedures are kept in order. ParamEnv
@@ -1182,7 +1173,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
11821173 ProjectionCandidate :: TraitDef ,
11831174 bounds. iter ( ) ,
11841175 true ,
1185- )
1176+ ) ;
11861177}
11871178
11881179/// In the case of a trait object like
@@ -1247,28 +1238,35 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
12471238 let bound_predicate = predicate. kind ( ) ;
12481239 if let ty:: PredicateKind :: Projection ( data) = predicate. kind ( ) . skip_binder ( ) {
12491240 let data = bound_predicate. rebind ( data) ;
1250- let same_def_id = data. projection_def_id ( ) == obligation. predicate . item_def_id ;
1251-
1252- let is_match = same_def_id
1253- && infcx. probe ( |_| {
1254- selcx. match_projection_projections (
1255- obligation,
1256- data,
1257- potentially_unnormalized_candidates,
1258- )
1259- } ) ;
1241+ if data. projection_def_id ( ) != obligation. predicate . item_def_id {
1242+ continue ;
1243+ }
12601244
1261- if is_match {
1262- candidate_set. push_candidate ( ctor ( data) ) ;
1245+ let is_match = infcx. probe ( |_| {
1246+ selcx. match_projection_projections (
1247+ obligation,
1248+ data,
1249+ potentially_unnormalized_candidates,
1250+ )
1251+ } ) ;
12631252
1264- if potentially_unnormalized_candidates
1265- && !obligation. predicate . has_infer_types_or_consts ( )
1266- {
1267- // HACK: Pick the first trait def candidate for a fully
1268- // inferred predicate. This is to allow duplicates that
1269- // differ only in normalization.
1270- return ;
1253+ match is_match {
1254+ ProjectionMatchesProjection :: Yes => {
1255+ candidate_set. push_candidate ( ctor ( data) ) ;
1256+
1257+ if potentially_unnormalized_candidates
1258+ && !obligation. predicate . has_infer_types_or_consts ( )
1259+ {
1260+ // HACK: Pick the first trait def candidate for a fully
1261+ // inferred predicate. This is to allow duplicates that
1262+ // differ only in normalization.
1263+ return ;
1264+ }
1265+ }
1266+ ProjectionMatchesProjection :: Ambiguous => {
1267+ candidate_set. mark_ambiguous ( ) ;
12711268 }
1269+ ProjectionMatchesProjection :: No => { }
12721270 }
12731271 }
12741272 }
0 commit comments