@@ -690,10 +690,76 @@ 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. is_late_bound ( ) || r_b. is_late_bound ( ) {
731
+ // There is no current way to prove `for<'a> 'a: 'x`
732
+ // unless `'a = 'x`, because there are no bounds involving
733
+ // lifetimes.
734
+
735
+ // It is possible to solve `for<'a> 'x: 'a` where `'x`
736
+ // is a free region by forcing `'x = 'static`. However,
737
+ // fulfillment does not *quite* do this ATM (it calls
738
+ // `region_outlives_predicate`, which is OK if `'x` is
739
+ // literally ReStatic, but is *not* OK if `'x` is any
740
+ // sort of inference variable, even if it *is* equal
741
+ // to `'static`).
742
+
743
+ // If we ever want to handle that sort of obligations,
744
+ // we need to make sure we are not confused by
745
+ // technically-allowed-by-RFC-447-but-probably-should-not-be
746
+ // impls such as
747
+ // ```Rust
748
+ // impl<'a, 's, T> X<'s> for T where T: Debug + 's, 'a: 's
749
+ // ```
750
+
751
+ // We don't want to allow this sort of reasoning in intercrate
752
+ // mode, for backwards-compatibility reasons.
753
+ if self . intercrate . is_some ( ) {
754
+ Ok ( EvaluatedToAmbig )
755
+ } else {
756
+ Ok ( EvaluatedToErr )
757
+ }
758
+ } else {
759
+ // Relating 2 inference variable regions. These will
760
+ // always hold if our query is "staticized".
761
+ Ok ( EvaluatedToOk )
762
+ }
697
763
}
698
764
699
765
ty:: Predicate :: ObjectSafe ( trait_def_id) => {
@@ -900,6 +966,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
900
966
{
901
967
debug ! ( "evaluate_stack({:?}) --> recursive" ,
902
968
stack. fresh_trait_ref) ;
969
+
903
970
let cycle = stack. iter ( ) . skip ( 1 ) . take ( rec_index + 1 ) ;
904
971
let cycle = cycle. map ( |stack| ty:: Predicate :: Trait ( stack. obligation . predicate ) ) ;
905
972
if self . coinductive_match ( cycle) {
0 commit comments