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