@@ -41,6 +41,8 @@ pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'
4141
4242pub type ProjectionTyObligation < ' tcx > = Obligation < ' tcx , ty:: ProjectionTy < ' tcx > > ;
4343
44+ pub ( super ) struct InProgress ;
45+
4446/// When attempting to resolve `<T as TraitRef>::Name` ...
4547#[ derive( Debug ) ]
4648pub enum ProjectionTyError < ' tcx > {
@@ -143,10 +145,26 @@ impl<'tcx> ProjectionTyCandidateSet<'tcx> {
143145///
144146/// If successful, this may result in additional obligations. Also returns
145147/// the projection cache key used to track these additional obligations.
146- pub fn poly_project_and_unify_type < ' cx , ' tcx > (
148+ ///
149+ /// ## Returns
150+ ///
151+ /// - `Err(_)`: the projection can be normalized, but is not equal to the
152+ /// expected type.
153+ /// - `Ok(Err(InProgress))`: this is called recursively while normalizing
154+ /// the same projection.
155+ /// - `Ok(Ok(None))`: The projection cannot be normalized due to ambiguity
156+ /// (resolving some inference variables in the projection may fix this).
157+ /// - `Ok(Ok(Some(obligations)))`: The projection bound holds subject to
158+ /// the given obligations. If the projection cannot be normalized because
159+ /// the required trait bound doesn't hold this returned with `obligations`
160+ /// being a predicate that cannot be proven.
161+ pub ( super ) fn poly_project_and_unify_type < ' cx , ' tcx > (
147162 selcx : & mut SelectionContext < ' cx , ' tcx > ,
148163 obligation : & PolyProjectionObligation < ' tcx > ,
149- ) -> Result < Option < Vec < PredicateObligation < ' tcx > > > , MismatchedProjectionTypes < ' tcx > > {
164+ ) -> Result <
165+ Result < Option < Vec < PredicateObligation < ' tcx > > > , InProgress > ,
166+ MismatchedProjectionTypes < ' tcx > ,
167+ > {
150168 debug ! ( "poly_project_and_unify_type(obligation={:?})" , obligation) ;
151169
152170 let infcx = selcx. infcx ( ) ;
@@ -165,10 +183,15 @@ pub fn poly_project_and_unify_type<'cx, 'tcx>(
165183/// <T as Trait>::U == V
166184///
167185/// If successful, this may result in additional obligations.
186+ ///
187+ /// See [poly_project_and_unify_type] for an explanation of the return value.
168188fn project_and_unify_type < ' cx , ' tcx > (
169189 selcx : & mut SelectionContext < ' cx , ' tcx > ,
170190 obligation : & ProjectionObligation < ' tcx > ,
171- ) -> Result < Option < Vec < PredicateObligation < ' tcx > > > , MismatchedProjectionTypes < ' tcx > > {
191+ ) -> Result <
192+ Result < Option < Vec < PredicateObligation < ' tcx > > > , InProgress > ,
193+ MismatchedProjectionTypes < ' tcx > ,
194+ > {
172195 debug ! ( "project_and_unify_type(obligation={:?})" , obligation) ;
173196
174197 let mut obligations = vec ! [ ] ;
@@ -180,8 +203,9 @@ fn project_and_unify_type<'cx, 'tcx>(
180203 obligation. recursion_depth ,
181204 & mut obligations,
182205 ) {
183- Some ( n) => n,
184- None => return Ok ( None ) ,
206+ Ok ( Some ( n) ) => n,
207+ Ok ( None ) => return Ok ( Ok ( None ) ) ,
208+ Err ( InProgress ) => return Ok ( Err ( InProgress ) ) ,
185209 } ;
186210
187211 debug ! (
@@ -196,7 +220,7 @@ fn project_and_unify_type<'cx, 'tcx>(
196220 {
197221 Ok ( InferOk { obligations : inferred_obligations, value : ( ) } ) => {
198222 obligations. extend ( inferred_obligations) ;
199- Ok ( Some ( obligations) )
223+ Ok ( Ok ( Some ( obligations) ) )
200224 }
201225 Err ( err) => {
202226 debug ! ( "project_and_unify_type: equating types encountered error {:?}" , err) ;
@@ -419,6 +443,8 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>(
419443 depth,
420444 obligations,
421445 )
446+ . ok ( )
447+ . flatten ( )
422448 . unwrap_or_else ( move || {
423449 // if we bottom out in ambiguity, create a type variable
424450 // and a deferred predicate to resolve this when more type
@@ -455,7 +481,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
455481 cause : ObligationCause < ' tcx > ,
456482 depth : usize ,
457483 obligations : & mut Vec < PredicateObligation < ' tcx > > ,
458- ) -> Option < Ty < ' tcx > > {
484+ ) -> Result < Option < Ty < ' tcx > > , InProgress > {
459485 let infcx = selcx. infcx ( ) ;
460486
461487 let projection_ty = infcx. resolve_vars_if_possible ( & projection_ty) ;
@@ -487,7 +513,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
487513 "opt_normalize_projection_type: \
488514 found cache entry: ambiguous"
489515 ) ;
490- return None ;
516+ return Ok ( None ) ;
491517 }
492518 Err ( ProjectionCacheEntry :: InProgress ) => {
493519 // If while normalized A::B, we are asked to normalize
@@ -502,24 +528,14 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
502528 // to normalize `A::B`, we will want to check the
503529 // where-clauses in scope. So we will try to unify `A::B`
504530 // with `A::B`, which can trigger a recursive
505- // normalization. In that case, I think we will want this code:
506- //
507- // ```
508- // let ty = selcx.tcx().mk_projection(projection_ty.item_def_id,
509- // projection_ty.substs;
510- // return Some(NormalizedTy { value: v, obligations: vec![] });
511- // ```
531+ // normalization.
512532
513533 debug ! (
514534 "opt_normalize_projection_type: \
515535 found cache entry: in-progress"
516536 ) ;
517537
518- // But for now, let's classify this as an overflow:
519- let recursion_limit = selcx. tcx ( ) . sess . recursion_limit ( ) ;
520- let obligation =
521- Obligation :: with_depth ( cause, recursion_limit. 0 , param_env, projection_ty) ;
522- selcx. infcx ( ) . report_overflow_error ( & obligation, false ) ;
538+ return Err ( InProgress ) ;
523539 }
524540 Err ( ProjectionCacheEntry :: NormalizedTy ( ty) ) => {
525541 // This is the hottest path in this function.
@@ -555,7 +571,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
555571 cause,
556572 depth,
557573 ) ) ;
558- return Some ( ty. value ) ;
574+ return Ok ( Some ( ty. value ) ) ;
559575 }
560576 Err ( ProjectionCacheEntry :: Error ) => {
561577 debug ! (
@@ -564,7 +580,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
564580 ) ;
565581 let result = normalize_to_error ( selcx, param_env, projection_ty, cause, depth) ;
566582 obligations. extend ( result. obligations ) ;
567- return Some ( result. value ) ;
583+ return Ok ( Some ( result. value ) ) ;
568584 }
569585 }
570586
@@ -611,7 +627,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
611627 let cache_value = prune_cache_value_obligations ( infcx, & result) ;
612628 infcx. inner . borrow_mut ( ) . projection_cache ( ) . insert_ty ( cache_key, cache_value) ;
613629 obligations. extend ( result. obligations ) ;
614- Some ( result. value )
630+ Ok ( Some ( result. value ) )
615631 }
616632 Ok ( ProjectedTy :: NoProgress ( projected_ty) ) => {
617633 debug ! (
@@ -622,15 +638,15 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
622638 let result = Normalized { value : projected_ty, obligations : vec ! [ ] } ;
623639 infcx. inner . borrow_mut ( ) . projection_cache ( ) . insert_ty ( cache_key, result. clone ( ) ) ;
624640 // No need to extend `obligations`.
625- Some ( result. value )
641+ Ok ( Some ( result. value ) )
626642 }
627643 Err ( ProjectionTyError :: TooManyCandidates ) => {
628644 debug ! (
629645 "opt_normalize_projection_type: \
630646 too many candidates"
631647 ) ;
632648 infcx. inner . borrow_mut ( ) . projection_cache ( ) . ambiguous ( cache_key) ;
633- None
649+ Ok ( None )
634650 }
635651 Err ( ProjectionTyError :: TraitSelectionError ( _) ) => {
636652 debug ! ( "opt_normalize_projection_type: ERROR" ) ;
@@ -642,7 +658,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
642658 infcx. inner . borrow_mut ( ) . projection_cache ( ) . error ( cache_key) ;
643659 let result = normalize_to_error ( selcx, param_env, projection_ty, cause, depth) ;
644660 obligations. extend ( result. obligations ) ;
645- Some ( result. value )
661+ Ok ( Some ( result. value ) )
646662 }
647663 }
648664}
@@ -1116,11 +1132,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
11161132 }
11171133 super :: ImplSourceAutoImpl ( ..) | super :: ImplSourceBuiltin ( ..) => {
11181134 // These traits have no associated types.
1119- span_bug ! (
1135+ selcx . tcx ( ) . sess . delay_span_bug (
11201136 obligation. cause . span ,
1121- "Cannot project an associated type from `{:?}`" ,
1122- impl_source
1137+ & format ! ( "Cannot project an associated type from `{:?}`" , impl_source) ,
11231138 ) ;
1139+ return Err ( ( ) ) ;
11241140 }
11251141 } ;
11261142
0 commit comments