@@ -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 ( ty:: TyVar ( _) ) => {
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 ( ) {
@@ -348,6 +356,12 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
348356 // WfScalar, WfParameter, etc
349357 }
350358
359+ // Can only infer to `ty::Int(_) | ty::Uint(_)`.
360+ ty:: Infer ( ty:: IntVar ( _) ) => { }
361+
362+ // Can only infer to `ty::Float(_)`.
363+ ty:: Infer ( ty:: FloatVar ( _) ) => { }
364+
351365 ty:: Slice ( subty) => {
352366 self . require_sized ( subty, traits:: SliceOrArrayElem ) ;
353367 }
@@ -442,8 +456,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
442456 // are not directly inspecting closure types
443457 // anyway, except via auto trait matching (which
444458 // only inspects the upvar types).
445- walker. skip_current_subtree ( ) ; // subtree handled by compute_projection
459+ walker. skip_current_subtree ( ) ; // subtree handled below
446460 for upvar_ty in substs. as_closure ( ) . upvar_tys ( ) {
461+ // FIXME(eddyb) add the type to `walker` instead of recursing.
447462 self . compute ( upvar_ty) ;
448463 }
449464 }
@@ -496,44 +511,31 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
496511 //
497512 // 1. Check if they have been resolved, and if so proceed with
498513 // 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
514+ // 2. If not, we've at least simplified things (e.g., we went
515+ // from `Vec<$0>: WF` to `$0: WF`), so we can
504516 // register a pending obligation and keep
505517 // moving. (Goal is that an "inductive hypothesis"
506518 // is satisfied to ensure termination.)
519+ // See also the comment on `fn obligations`, describing "livelock"
520+ // prevention, which happens before this can be reached.
507521 ty:: Infer ( _) => {
508522 let ty = self . infcx . shallow_resolve ( ty) ;
509- 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-
523+ if let ty:: Infer ( ty:: TyVar ( _) ) = ty. kind {
524+ // Not yet resolved, but we've made progress.
516525 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- ) ;
526+ self . out . push ( traits:: Obligation :: new (
527+ cause,
528+ param_env,
529+ ty:: Predicate :: WellFormed ( ty) ,
530+ ) ) ;
525531 } 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) ) ;
532+ // Yes, resolved, proceed with the result.
533+ // FIXME(eddyb) add the type to `walker` instead of recursing.
534+ self . compute ( ty) ;
530535 }
531536 }
532537 }
533538 }
534-
535- // if we made it through that loop above, we made progress!
536- true
537539 }
538540
539541 fn nominal_obligations (
0 commit comments