@@ -41,6 +41,8 @@ pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'
41
41
42
42
pub type ProjectionTyObligation < ' tcx > = Obligation < ' tcx , ty:: ProjectionTy < ' tcx > > ;
43
43
44
+ pub ( super ) struct InProgress ;
45
+
44
46
/// When attempting to resolve `<T as TraitRef>::Name` ...
45
47
#[ derive( Debug ) ]
46
48
pub enum ProjectionTyError < ' tcx > {
@@ -143,10 +145,26 @@ impl<'tcx> ProjectionTyCandidateSet<'tcx> {
143
145
///
144
146
/// If successful, this may result in additional obligations. Also returns
145
147
/// 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 > (
147
162
selcx : & mut SelectionContext < ' cx , ' tcx > ,
148
163
obligation : & PolyProjectionObligation < ' tcx > ,
149
- ) -> Result < Option < Vec < PredicateObligation < ' tcx > > > , MismatchedProjectionTypes < ' tcx > > {
164
+ ) -> Result <
165
+ Result < Option < Vec < PredicateObligation < ' tcx > > > , InProgress > ,
166
+ MismatchedProjectionTypes < ' tcx > ,
167
+ > {
150
168
debug ! ( "poly_project_and_unify_type(obligation={:?})" , obligation) ;
151
169
152
170
let infcx = selcx. infcx ( ) ;
@@ -165,10 +183,15 @@ pub fn poly_project_and_unify_type<'cx, 'tcx>(
165
183
/// <T as Trait>::U == V
166
184
///
167
185
/// If successful, this may result in additional obligations.
186
+ ///
187
+ /// See [poly_project_and_unify_type] for an explanation of the return value.
168
188
fn project_and_unify_type < ' cx , ' tcx > (
169
189
selcx : & mut SelectionContext < ' cx , ' tcx > ,
170
190
obligation : & ProjectionObligation < ' tcx > ,
171
- ) -> Result < Option < Vec < PredicateObligation < ' tcx > > > , MismatchedProjectionTypes < ' tcx > > {
191
+ ) -> Result <
192
+ Result < Option < Vec < PredicateObligation < ' tcx > > > , InProgress > ,
193
+ MismatchedProjectionTypes < ' tcx > ,
194
+ > {
172
195
debug ! ( "project_and_unify_type(obligation={:?})" , obligation) ;
173
196
174
197
let mut obligations = vec ! [ ] ;
@@ -180,8 +203,9 @@ fn project_and_unify_type<'cx, 'tcx>(
180
203
obligation. recursion_depth ,
181
204
& mut obligations,
182
205
) {
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 ) ) ,
185
209
} ;
186
210
187
211
debug ! (
@@ -196,7 +220,7 @@ fn project_and_unify_type<'cx, 'tcx>(
196
220
{
197
221
Ok ( InferOk { obligations : inferred_obligations, value : ( ) } ) => {
198
222
obligations. extend ( inferred_obligations) ;
199
- Ok ( Some ( obligations) )
223
+ Ok ( Ok ( Some ( obligations) ) )
200
224
}
201
225
Err ( err) => {
202
226
debug ! ( "project_and_unify_type: equating types encountered error {:?}" , err) ;
@@ -419,6 +443,8 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>(
419
443
depth,
420
444
obligations,
421
445
)
446
+ . ok ( )
447
+ . flatten ( )
422
448
. unwrap_or_else ( move || {
423
449
// if we bottom out in ambiguity, create a type variable
424
450
// and a deferred predicate to resolve this when more type
@@ -455,7 +481,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
455
481
cause : ObligationCause < ' tcx > ,
456
482
depth : usize ,
457
483
obligations : & mut Vec < PredicateObligation < ' tcx > > ,
458
- ) -> Option < Ty < ' tcx > > {
484
+ ) -> Result < Option < Ty < ' tcx > > , InProgress > {
459
485
let infcx = selcx. infcx ( ) ;
460
486
461
487
let projection_ty = infcx. resolve_vars_if_possible ( & projection_ty) ;
@@ -487,7 +513,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
487
513
"opt_normalize_projection_type: \
488
514
found cache entry: ambiguous"
489
515
) ;
490
- return None ;
516
+ return Ok ( None ) ;
491
517
}
492
518
Err ( ProjectionCacheEntry :: InProgress ) => {
493
519
// If while normalized A::B, we are asked to normalize
@@ -502,24 +528,14 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
502
528
// to normalize `A::B`, we will want to check the
503
529
// where-clauses in scope. So we will try to unify `A::B`
504
530
// 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.
512
532
513
533
debug ! (
514
534
"opt_normalize_projection_type: \
515
535
found cache entry: in-progress"
516
536
) ;
517
537
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 ) ;
523
539
}
524
540
Err ( ProjectionCacheEntry :: NormalizedTy ( ty) ) => {
525
541
// This is the hottest path in this function.
@@ -555,7 +571,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
555
571
cause,
556
572
depth,
557
573
) ) ;
558
- return Some ( ty. value ) ;
574
+ return Ok ( Some ( ty. value ) ) ;
559
575
}
560
576
Err ( ProjectionCacheEntry :: Error ) => {
561
577
debug ! (
@@ -564,7 +580,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
564
580
) ;
565
581
let result = normalize_to_error ( selcx, param_env, projection_ty, cause, depth) ;
566
582
obligations. extend ( result. obligations ) ;
567
- return Some ( result. value ) ;
583
+ return Ok ( Some ( result. value ) ) ;
568
584
}
569
585
}
570
586
@@ -611,7 +627,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
611
627
let cache_value = prune_cache_value_obligations ( infcx, & result) ;
612
628
infcx. inner . borrow_mut ( ) . projection_cache ( ) . insert_ty ( cache_key, cache_value) ;
613
629
obligations. extend ( result. obligations ) ;
614
- Some ( result. value )
630
+ Ok ( Some ( result. value ) )
615
631
}
616
632
Ok ( ProjectedTy :: NoProgress ( projected_ty) ) => {
617
633
debug ! (
@@ -622,15 +638,15 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
622
638
let result = Normalized { value : projected_ty, obligations : vec ! [ ] } ;
623
639
infcx. inner . borrow_mut ( ) . projection_cache ( ) . insert_ty ( cache_key, result. clone ( ) ) ;
624
640
// No need to extend `obligations`.
625
- Some ( result. value )
641
+ Ok ( Some ( result. value ) )
626
642
}
627
643
Err ( ProjectionTyError :: TooManyCandidates ) => {
628
644
debug ! (
629
645
"opt_normalize_projection_type: \
630
646
too many candidates"
631
647
) ;
632
648
infcx. inner . borrow_mut ( ) . projection_cache ( ) . ambiguous ( cache_key) ;
633
- None
649
+ Ok ( None )
634
650
}
635
651
Err ( ProjectionTyError :: TraitSelectionError ( _) ) => {
636
652
debug ! ( "opt_normalize_projection_type: ERROR" ) ;
@@ -642,7 +658,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
642
658
infcx. inner . borrow_mut ( ) . projection_cache ( ) . error ( cache_key) ;
643
659
let result = normalize_to_error ( selcx, param_env, projection_ty, cause, depth) ;
644
660
obligations. extend ( result. obligations ) ;
645
- Some ( result. value )
661
+ Ok ( Some ( result. value ) )
646
662
}
647
663
}
648
664
}
@@ -1116,11 +1132,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
1116
1132
}
1117
1133
super :: ImplSourceAutoImpl ( ..) | super :: ImplSourceBuiltin ( ..) => {
1118
1134
// These traits have no associated types.
1119
- span_bug ! (
1135
+ selcx . tcx ( ) . sess . delay_span_bug (
1120
1136
obligation. cause . span ,
1121
- "Cannot project an associated type from `{:?}`" ,
1122
- impl_source
1137
+ & format ! ( "Cannot project an associated type from `{:?}`" , impl_source) ,
1123
1138
) ;
1139
+ return Err ( ( ) ) ;
1124
1140
}
1125
1141
} ;
1126
1142
0 commit comments