@@ -22,16 +22,27 @@ pub fn obligations<'a, 'tcx>(
2222 ty : Ty < ' tcx > ,
2323 span : Span ,
2424) -> Option < Vec < traits:: PredicateObligation < ' tcx > > > {
25+ // Handle the "livelock" case (see comment above) by bailing out if necessary.
26+ let ty = match ty. kind {
27+ ty:: Infer ( _) => {
28+ let resolved_ty = infcx. shallow_resolve ( ty) ;
29+ if resolved_ty == ty {
30+ // No progress, bail out to prevent "livelock".
31+ return None ;
32+ }
33+
34+ resolved_ty
35+ }
36+ _ => ty,
37+ } ;
38+
2539 let mut wf = WfPredicates { infcx, param_env, body_id, span, out : vec ! [ ] , item : None } ;
26- if wf. compute ( ty) {
27- debug ! ( "wf::obligations({:?}, body_id={:?}) = {:?}" , ty, body_id, wf. out) ;
28-
29- let result = wf. normalize ( ) ;
30- debug ! ( "wf::obligations({:?}, body_id={:?}) ~~> {:?}" , ty, body_id, result) ;
31- Some ( result)
32- } else {
33- None // no progress made, return None
34- }
40+ wf. compute ( ty) ;
41+ debug ! ( "wf::obligations({:?}, body_id={:?}) = {:?}" , ty, body_id, wf. out) ;
42+
43+ let result = wf. normalize ( ) ;
44+ debug ! ( "wf::obligations({:?}, body_id={:?}) ~~> {:?}" , ty, body_id, result) ;
45+ Some ( result)
3546}
3647
3748/// Returns the obligations that make this trait reference
@@ -311,12 +322,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
311322 }
312323 }
313324
314- /// Pushes new obligations into `out`. Returns `true` if it was able
315- /// to generate all the predicates needed to validate that `ty0`
316- /// is WF. Returns false if `ty0` is an unresolved type variable,
317- /// in which case we are not able to simplify at all.
318- fn compute ( & mut self , ty0 : Ty < ' tcx > ) -> bool {
319- let mut walker = ty0. walk ( ) ;
325+ /// Pushes all the predicates needed to validate that `ty` is WF into `out`.
326+ fn compute ( & mut self , ty : Ty < ' tcx > ) {
327+ let mut walker = ty. walk ( ) ;
320328 let param_env = self . param_env ;
321329 while let Some ( arg) = walker. next ( ) {
322330 let ty = match arg. unpack ( ) {
@@ -442,8 +450,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
442450 // are not directly inspecting closure types
443451 // anyway, except via auto trait matching (which
444452 // only inspects the upvar types).
445- walker. skip_current_subtree ( ) ; // subtree handled by compute_projection
453+ walker. skip_current_subtree ( ) ; // subtree handled below
446454 for upvar_ty in substs. as_closure ( ) . upvar_tys ( ) {
455+ // FIXME(eddyb) add the type to `walker` instead of recursing.
447456 self . compute ( upvar_ty) ;
448457 }
449458 }
@@ -496,44 +505,31 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
496505 //
497506 // 1. Check if they have been resolved, and if so proceed with
498507 // THAT type.
499- // 2. If not, check whether this is the type that we
500- // started with (ty0). In that case, we've made no
501- // progress at all, so return false. Otherwise,
502- // we've at least simplified things (i.e., we went
503- // from `Vec<$0>: WF` to `$0: WF`, so we can
508+ // 2. If not, we've at least simplified things (e.g., we went
509+ // from `Vec<$0>: WF` to `$0: WF`), so we can
504510 // register a pending obligation and keep
505511 // moving. (Goal is that an "inductive hypothesis"
506512 // is satisfied to ensure termination.)
513+ // See also the comment on `fn obligations`, describing "livelock"
514+ // prevention, which happens before this can be reached.
507515 ty:: Infer ( _) => {
508516 let ty = self . infcx . shallow_resolve ( ty) ;
509517 if let ty:: Infer ( _) = ty. kind {
510- // not yet resolved...
511- if ty == ty0 {
512- // ...this is the type we started from! no progress.
513- return false ;
514- }
515-
518+ // Not yet resolved, but we've made progress.
516519 let cause = self . cause ( traits:: MiscObligation ) ;
517- self . out . push (
518- // ...not the type we started from, so we made progress.
519- traits:: Obligation :: new (
520- cause,
521- self . param_env ,
522- ty:: Predicate :: WellFormed ( ty) ,
523- ) ,
524- ) ;
520+ self . out . push ( traits:: Obligation :: new (
521+ cause,
522+ param_env,
523+ ty:: Predicate :: WellFormed ( ty) ,
524+ ) ) ;
525525 } else {
526- // Yes, resolved, proceed with the
527- // result. Should never return false because
528- // `ty` is not a Infer.
529- assert ! ( self . compute( ty) ) ;
526+ // Yes, resolved, proceed with the result.
527+ // FIXME(eddyb) add the type to `walker` instead of recursing.
528+ self . compute ( ty) ;
530529 }
531530 }
532531 }
533532 }
534-
535- // if we made it through that loop above, we made progress!
536- true
537533 }
538534
539535 fn nominal_obligations (
0 commit comments