@@ -40,6 +40,8 @@ pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'
4040
4141pub type ProjectionTyObligation < ' tcx > = Obligation < ' tcx , ty:: ProjectionTy < ' tcx > > ;
4242
43+ pub ( super ) struct InProgress ;
44+
4345/// When attempting to resolve `<T as TraitRef>::Name` ...
4446#[ derive( Debug ) ]
4547pub enum ProjectionTyError < ' tcx > {
@@ -142,10 +144,26 @@ impl<'tcx> ProjectionTyCandidateSet<'tcx> {
142144///
143145/// If successful, this may result in additional obligations. Also returns
144146/// the projection cache key used to track these additional obligations.
145- pub fn poly_project_and_unify_type < ' cx , ' tcx > (
147+ ///
148+ /// ## Returns
149+ ///
150+ /// - `Err(_)`: the projection can be normalized, but is not equal to the
151+ /// expected type.
152+ /// - `Ok(Err(InProgress))`: this is called recursively while normalizing
153+ /// the same projection.
154+ /// - `Ok(Ok(None))`: The projection cannot be normalized due to ambiguity
155+ /// (resolving some inference variables in the projection may fix this).
156+ /// - `Ok(Ok(Some(obligations)))`: The projection bound holds subject to
157+ /// the given obligations. If the projection cannot be normalized because
158+ /// the required trait bound doesn't hold this returned with `obligations`
159+ /// being a predicate that cannot be proven.
160+ pub ( super ) fn poly_project_and_unify_type < ' cx , ' tcx > (
146161 selcx : & mut SelectionContext < ' cx , ' tcx > ,
147162 obligation : & PolyProjectionObligation < ' tcx > ,
148- ) -> Result < Option < Vec < PredicateObligation < ' tcx > > > , MismatchedProjectionTypes < ' tcx > > {
163+ ) -> Result <
164+ Result < Option < Vec < PredicateObligation < ' tcx > > > , InProgress > ,
165+ MismatchedProjectionTypes < ' tcx > ,
166+ > {
149167 debug ! ( "poly_project_and_unify_type(obligation={:?})" , obligation) ;
150168
151169 let infcx = selcx. infcx ( ) ;
@@ -164,10 +182,15 @@ pub fn poly_project_and_unify_type<'cx, 'tcx>(
164182/// <T as Trait>::U == V
165183///
166184/// If successful, this may result in additional obligations.
185+ ///
186+ /// See [poly_project_and_unify_type] for an explanation of the return value.
167187fn project_and_unify_type < ' cx , ' tcx > (
168188 selcx : & mut SelectionContext < ' cx , ' tcx > ,
169189 obligation : & ProjectionObligation < ' tcx > ,
170- ) -> Result < Option < Vec < PredicateObligation < ' tcx > > > , MismatchedProjectionTypes < ' tcx > > {
190+ ) -> Result <
191+ Result < Option < Vec < PredicateObligation < ' tcx > > > , InProgress > ,
192+ MismatchedProjectionTypes < ' tcx > ,
193+ > {
171194 debug ! ( "project_and_unify_type(obligation={:?})" , obligation) ;
172195
173196 let mut obligations = vec ! [ ] ;
@@ -179,8 +202,9 @@ fn project_and_unify_type<'cx, 'tcx>(
179202 obligation. recursion_depth ,
180203 & mut obligations,
181204 ) {
182- Some ( n) => n,
183- None => return Ok ( None ) ,
205+ Ok ( Some ( n) ) => n,
206+ Ok ( None ) => return Ok ( Ok ( None ) ) ,
207+ Err ( InProgress ) => return Ok ( Err ( InProgress ) ) ,
184208 } ;
185209
186210 debug ! (
@@ -195,7 +219,7 @@ fn project_and_unify_type<'cx, 'tcx>(
195219 {
196220 Ok ( InferOk { obligations : inferred_obligations, value : ( ) } ) => {
197221 obligations. extend ( inferred_obligations) ;
198- Ok ( Some ( obligations) )
222+ Ok ( Ok ( Some ( obligations) ) )
199223 }
200224 Err ( err) => {
201225 debug ! ( "project_and_unify_type: equating types encountered error {:?}" , err) ;
@@ -418,6 +442,8 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>(
418442 depth,
419443 obligations,
420444 )
445+ . ok ( )
446+ . flatten ( )
421447 . unwrap_or_else ( move || {
422448 // if we bottom out in ambiguity, create a type variable
423449 // and a deferred predicate to resolve this when more type
@@ -454,7 +480,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
454480 cause : ObligationCause < ' tcx > ,
455481 depth : usize ,
456482 obligations : & mut Vec < PredicateObligation < ' tcx > > ,
457- ) -> Option < Ty < ' tcx > > {
483+ ) -> Result < Option < Ty < ' tcx > > , InProgress > {
458484 let infcx = selcx. infcx ( ) ;
459485
460486 let projection_ty = infcx. resolve_vars_if_possible ( & projection_ty) ;
@@ -486,7 +512,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
486512 "opt_normalize_projection_type: \
487513 found cache entry: ambiguous"
488514 ) ;
489- return None ;
515+ return Ok ( None ) ;
490516 }
491517 Err ( ProjectionCacheEntry :: InProgress ) => {
492518 // If while normalized A::B, we are asked to normalize
@@ -501,24 +527,14 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
501527 // to normalize `A::B`, we will want to check the
502528 // where-clauses in scope. So we will try to unify `A::B`
503529 // with `A::B`, which can trigger a recursive
504- // normalization. In that case, I think we will want this code:
505- //
506- // ```
507- // let ty = selcx.tcx().mk_projection(projection_ty.item_def_id,
508- // projection_ty.substs;
509- // return Some(NormalizedTy { value: v, obligations: vec![] });
510- // ```
530+ // normalization.
511531
512532 debug ! (
513533 "opt_normalize_projection_type: \
514534 found cache entry: in-progress"
515535 ) ;
516536
517- // But for now, let's classify this as an overflow:
518- let recursion_limit = selcx. tcx ( ) . sess . recursion_limit ( ) ;
519- let obligation =
520- Obligation :: with_depth ( cause, recursion_limit. 0 , param_env, projection_ty) ;
521- selcx. infcx ( ) . report_overflow_error ( & obligation, false ) ;
537+ return Err ( InProgress ) ;
522538 }
523539 Err ( ProjectionCacheEntry :: NormalizedTy ( ty) ) => {
524540 // This is the hottest path in this function.
@@ -554,7 +570,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
554570 cause,
555571 depth,
556572 ) ) ;
557- return Some ( ty. value ) ;
573+ return Ok ( Some ( ty. value ) ) ;
558574 }
559575 Err ( ProjectionCacheEntry :: Error ) => {
560576 debug ! (
@@ -563,7 +579,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
563579 ) ;
564580 let result = normalize_to_error ( selcx, param_env, projection_ty, cause, depth) ;
565581 obligations. extend ( result. obligations ) ;
566- return Some ( result. value ) ;
582+ return Ok ( Some ( result. value ) ) ;
567583 }
568584 }
569585
@@ -610,7 +626,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
610626 let cache_value = prune_cache_value_obligations ( infcx, & result) ;
611627 infcx. inner . borrow_mut ( ) . projection_cache ( ) . insert_ty ( cache_key, cache_value) ;
612628 obligations. extend ( result. obligations ) ;
613- Some ( result. value )
629+ Ok ( Some ( result. value ) )
614630 }
615631 Ok ( ProjectedTy :: NoProgress ( projected_ty) ) => {
616632 debug ! (
@@ -621,15 +637,15 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
621637 let result = Normalized { value : projected_ty, obligations : vec ! [ ] } ;
622638 infcx. inner . borrow_mut ( ) . projection_cache ( ) . insert_ty ( cache_key, result. clone ( ) ) ;
623639 // No need to extend `obligations`.
624- Some ( result. value )
640+ Ok ( Some ( result. value ) )
625641 }
626642 Err ( ProjectionTyError :: TooManyCandidates ) => {
627643 debug ! (
628644 "opt_normalize_projection_type: \
629645 too many candidates"
630646 ) ;
631647 infcx. inner . borrow_mut ( ) . projection_cache ( ) . ambiguous ( cache_key) ;
632- None
648+ Ok ( None )
633649 }
634650 Err ( ProjectionTyError :: TraitSelectionError ( _) ) => {
635651 debug ! ( "opt_normalize_projection_type: ERROR" ) ;
@@ -641,7 +657,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
641657 infcx. inner . borrow_mut ( ) . projection_cache ( ) . error ( cache_key) ;
642658 let result = normalize_to_error ( selcx, param_env, projection_ty, cause, depth) ;
643659 obligations. extend ( result. obligations ) ;
644- Some ( result. value )
660+ Ok ( Some ( result. value ) )
645661 }
646662 }
647663}
@@ -1112,11 +1128,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
11121128 }
11131129 super :: ImplSourceAutoImpl ( ..) | super :: ImplSourceBuiltin ( ..) => {
11141130 // These traits have no associated types.
1115- span_bug ! (
1131+ selcx . tcx ( ) . sess . delay_span_bug (
11161132 obligation. cause . span ,
1117- "Cannot project an associated type from `{:?}`" ,
1118- impl_source
1133+ & format ! ( "Cannot project an associated type from `{:?}`" , impl_source) ,
11191134 ) ;
1135+ return Err ( ( ) ) ;
11201136 }
11211137 } ;
11221138
0 commit comments