@@ -19,6 +19,7 @@ use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey};
19
19
use crate :: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
20
20
use crate :: infer:: { InferCtxt , InferOk , LateBoundRegionConversionTime } ;
21
21
use crate :: traits:: error_reporting:: InferCtxtExt as _;
22
+ use crate :: traits:: select:: ProjectionMatchesProjection ;
22
23
use rustc_data_structures:: sso:: SsoHashSet ;
23
24
use rustc_data_structures:: stack:: ensure_sufficient_stack;
24
25
use rustc_errors:: ErrorReported ;
@@ -1075,16 +1076,6 @@ fn project<'cx, 'tcx>(
1075
1076
return Ok ( Projected :: Progress ( Progress :: error ( selcx. tcx ( ) ) ) ) ;
1076
1077
}
1077
1078
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
-
1088
1079
let mut candidates = ProjectionCandidateSet :: None ;
1089
1080
1090
1081
// Make sure that the following procedures are kept in order. ParamEnv
@@ -1182,7 +1173,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
1182
1173
ProjectionCandidate :: TraitDef ,
1183
1174
bounds. iter ( ) ,
1184
1175
true ,
1185
- )
1176
+ ) ;
1186
1177
}
1187
1178
1188
1179
/// In the case of a trait object like
@@ -1247,28 +1238,35 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
1247
1238
let bound_predicate = predicate. kind ( ) ;
1248
1239
if let ty:: PredicateKind :: Projection ( data) = predicate. kind ( ) . skip_binder ( ) {
1249
1240
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
+ }
1260
1244
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
+ } ) ;
1263
1252
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 ( ) ;
1271
1268
}
1269
+ ProjectionMatchesProjection :: No => { }
1272
1270
}
1273
1271
}
1274
1272
}
0 commit comments