@@ -22,16 +22,27 @@ pub fn obligations<'a, 'tcx>(
22
22
ty : Ty < ' tcx > ,
23
23
span : Span ,
24
24
) -> 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
+
25
39
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)
35
46
}
36
47
37
48
/// Returns the obligations that make this trait reference
@@ -311,12 +322,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
311
322
}
312
323
}
313
324
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 ( ) ;
320
328
let param_env = self . param_env ;
321
329
while let Some ( arg) = walker. next ( ) {
322
330
let ty = match arg. unpack ( ) {
@@ -348,6 +356,12 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
348
356
// WfScalar, WfParameter, etc
349
357
}
350
358
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
+
351
365
ty:: Slice ( subty) => {
352
366
self . require_sized ( subty, traits:: SliceOrArrayElem ) ;
353
367
}
@@ -442,8 +456,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
442
456
// are not directly inspecting closure types
443
457
// anyway, except via auto trait matching (which
444
458
// only inspects the upvar types).
445
- walker. skip_current_subtree ( ) ; // subtree handled by compute_projection
459
+ walker. skip_current_subtree ( ) ; // subtree handled below
446
460
for upvar_ty in substs. as_closure ( ) . upvar_tys ( ) {
461
+ // FIXME(eddyb) add the type to `walker` instead of recursing.
447
462
self . compute ( upvar_ty) ;
448
463
}
449
464
}
@@ -496,44 +511,31 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
496
511
//
497
512
// 1. Check if they have been resolved, and if so proceed with
498
513
// 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
504
516
// register a pending obligation and keep
505
517
// moving. (Goal is that an "inductive hypothesis"
506
518
// is satisfied to ensure termination.)
519
+ // See also the comment on `fn obligations`, describing "livelock"
520
+ // prevention, which happens before this can be reached.
507
521
ty:: Infer ( _) => {
508
522
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.
516
525
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
+ ) ) ;
525
531
} 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) ;
530
535
}
531
536
}
532
537
}
533
538
}
534
-
535
- // if we made it through that loop above, we made progress!
536
- true
537
539
}
538
540
539
541
fn nominal_obligations (
0 commit comments