@@ -690,10 +690,92 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
690
690
}
691
691
}
692
692
693
- ty:: Predicate :: TypeOutlives ( ..) | ty:: Predicate :: RegionOutlives ( ..) => {
694
- // we do not consider region relationships when
695
- // evaluating trait matches
696
- Ok ( EvaluatedToOk )
693
+ ty:: Predicate :: TypeOutlives ( ref binder) => {
694
+ assert ! ( !binder. has_escaping_regions( ) ) ;
695
+ // Check if the type has higher-ranked regions.
696
+ if binder. skip_binder ( ) . 0 . has_escaping_regions ( ) {
697
+ // If so, this obligation is an error (for now). Eventually we should be
698
+ // able to support additional cases here, like `for<'a> &'a str: 'a`.
699
+
700
+ // NOTE: this hack is implemented in both trait fulfillment and
701
+ // evaluation. If you fix it in one place, make sure you fix it
702
+ // in the other.
703
+
704
+ // We don't want to allow this sort of reasoning in intercrate
705
+ // mode, for backwards-compatibility reasons.
706
+ if self . intercrate . is_some ( ) {
707
+ Ok ( EvaluatedToAmbig )
708
+ } else {
709
+ Ok ( EvaluatedToErr )
710
+ }
711
+ } else {
712
+ // If the type has no late bound regions, then if we assign all
713
+ // the inference variables in it to be 'static, then the type
714
+ // will be 'static itself.
715
+ //
716
+ // Therefore, `staticize(T): 'a` holds for any `'a`, so this
717
+ // obligation is fulfilled. Because evaluation works with
718
+ // staticized types (yes I know this is involved with #21974),
719
+ // we are 100% OK here.
720
+ Ok ( EvaluatedToOk )
721
+ }
722
+ }
723
+
724
+ ty:: Predicate :: RegionOutlives ( ref binder) => {
725
+ let ty:: OutlivesPredicate ( r_a, r_b) = binder. skip_binder ( ) ;
726
+
727
+ if r_a == r_b {
728
+ // for<'a> 'a: 'a. OK
729
+ Ok ( EvaluatedToOk )
730
+ } else if * * r_a == ty:: ReStatic {
731
+ // 'static: 'x always holds.
732
+ //
733
+ // This special case is handled somewhat inconsistently - if we
734
+ // have an inference variable that is supposed to be equal to
735
+ // `'static`, then we don't allow it to be equated to an LBR,
736
+ // but if we have a literal `'static`, then we *do*.
737
+ //
738
+ // This is actually consistent with how our region inference works.
739
+ //
740
+ // It would appear that this sort of inconsistency would
741
+ // cause "instability" problems with evaluation caching. However,
742
+ // evaluation caching is only for trait predicates, and when
743
+ // trait predicates create nested obligations, they contain
744
+ // inference variables for all the regions in the trait - the
745
+ // only way this codepath can be reached from trait predicate
746
+ // evaluation is when the user typed an explicit `where 'static: 'a`
747
+ // lifetime bound (in which case we want to return EvaluatedToOk).
748
+ //
749
+ // If we ever want to handle inference variables that might be
750
+ // equatable with ReStatic, we need to make sure we are not confused by
751
+ // technically-allowed-by-RFC-447-but-probably-should-not-be
752
+ // impls such as
753
+ // ```Rust
754
+ // impl<'a, 's, T> X<'s> for T where T: Debug + 'a, 'a: 's
755
+ // ```
756
+ Ok ( EvaluatedToOk )
757
+ } else if r_a. is_late_bound ( ) || r_b. is_late_bound ( ) {
758
+ // There is no current way to prove `for<'a> 'a: 'x`
759
+ // unless `'a = 'x`, because there are no bounds involving
760
+ // lifetimes.
761
+
762
+ // It might be possible to prove `for<'a> 'x: 'a` by forcing `'x`
763
+ // to be `'static`. However, this is not currently done by type
764
+ // inference unless `'x` is literally ReStatic. See the comment
765
+ // above.
766
+
767
+ // We don't want to allow this sort of reasoning in intercrate
768
+ // mode, for backwards-compatibility reasons.
769
+ if self . intercrate . is_some ( ) {
770
+ Ok ( EvaluatedToAmbig )
771
+ } else {
772
+ Ok ( EvaluatedToErr )
773
+ }
774
+ } else {
775
+ // Relating 2 inference variable regions. These will
776
+ // always hold if our query is "staticized".
777
+ Ok ( EvaluatedToOk )
778
+ }
697
779
}
698
780
699
781
ty:: Predicate :: ObjectSafe ( trait_def_id) => {
@@ -900,6 +982,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
900
982
{
901
983
debug ! ( "evaluate_stack({:?}) --> recursive" ,
902
984
stack. fresh_trait_ref) ;
985
+
903
986
let cycle = stack. iter ( ) . skip ( 1 ) . take ( rec_index + 1 ) ;
904
987
let cycle = cycle. map ( |stack| ty:: Predicate :: Trait ( stack. obligation . predicate ) ) ;
905
988
if self . coinductive_match ( cycle) {
0 commit comments