@@ -430,7 +430,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
430
430
None
431
431
} ;
432
432
433
- self . check_type_tests ( infcx, mir, outlives_requirements. as_mut ( ) ) ;
433
+ self . check_type_tests ( infcx, mir, mir_def_id , outlives_requirements. as_mut ( ) ) ;
434
434
435
435
self . check_universal_regions ( infcx, mir, mir_def_id, outlives_requirements. as_mut ( ) ) ;
436
436
@@ -504,6 +504,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
504
504
& self ,
505
505
infcx : & InferCtxt < ' _ , ' gcx , ' tcx > ,
506
506
mir : & Mir < ' tcx > ,
507
+ mir_def_id : DefId ,
507
508
mut propagated_outlives_requirements : Option < & mut Vec < ClosureOutlivesRequirement < ' gcx > > > ,
508
509
) {
509
510
let tcx = infcx. tcx ;
@@ -522,14 +523,56 @@ impl<'tcx> RegionInferenceContext<'tcx> {
522
523
}
523
524
524
525
// Oh the humanity. Obviously we will do better than this error eventually.
525
- tcx. sess . span_err (
526
- type_test. span ,
527
- & format ! (
528
- "`{}` does not outlive `{:?}`" ,
526
+ let lower_bound_region = self . to_error_region ( type_test. lower_bound ) ;
527
+ if let Some ( lower_bound_region) = lower_bound_region {
528
+ let region_scope_tree = & tcx. region_scope_tree ( mir_def_id) ;
529
+ infcx. report_generic_bound_failure (
530
+ region_scope_tree,
531
+ type_test. span ,
532
+ None ,
529
533
type_test. generic_kind ,
530
- type_test. lower_bound,
531
- ) ,
532
- ) ;
534
+ lower_bound_region,
535
+ ) ;
536
+ } else {
537
+ // FIXME. We should handle this case better. It
538
+ // indicates that we have e.g. some region variable
539
+ // whose value is like `'a+'b` where `'a` and `'b` are
540
+ // distinct unrelated univesal regions that are not
541
+ // known to outlive one another. It'd be nice to have
542
+ // some examples where this arises to decide how best
543
+ // to report it; we could probably handle it by
544
+ // iterating over the universal regions and reporting
545
+ // an error that multiple bounds are required.
546
+ tcx. sess . span_err (
547
+ type_test. span ,
548
+ & format ! (
549
+ "`{}` does not live long enough" ,
550
+ type_test. generic_kind,
551
+ ) ,
552
+ ) ;
553
+ }
554
+ }
555
+ }
556
+
557
+ /// Converts a region inference variable into a `ty::Region` that
558
+ /// we can use for error reporting. If `r` is universally bound,
559
+ /// then we use the name that we have on record for it. If `r` is
560
+ /// existentially bound, then we check its inferred value and try
561
+ /// to find a good name from that. Returns `None` if we can't find
562
+ /// one (e.g., this is just some random part of the CFG).
563
+ fn to_error_region ( & self , r : RegionVid ) -> Option < ty:: Region < ' tcx > > {
564
+ if self . universal_regions . is_universal_region ( r) {
565
+ return self . definitions [ r] . external_name ;
566
+ } else {
567
+ let inferred_values = self . inferred_values
568
+ . as_ref ( )
569
+ . expect ( "region values not yet inferred" ) ;
570
+ let upper_bound = self . universal_upper_bound ( r) ;
571
+ if inferred_values. contains ( r, upper_bound) {
572
+ self . to_error_region ( upper_bound)
573
+ } else {
574
+ None
575
+ }
533
576
}
534
577
}
535
578
@@ -663,6 +706,36 @@ impl<'tcx> RegionInferenceContext<'tcx> {
663
706
/// encoding `T` as part of `try_promote_type_test_subject` (see
664
707
/// that fn for details).
665
708
///
709
+ /// This is based on the result `'y` of `universal_upper_bound`,
710
+ /// except that it converts further takes the non-local upper
711
+ /// bound of `'y`, so that the final result is non-local.
712
+ fn non_local_universal_upper_bound ( & self , r : RegionVid ) -> RegionVid {
713
+ let inferred_values = self . inferred_values . as_ref ( ) . unwrap ( ) ;
714
+
715
+ debug ! (
716
+ "non_local_universal_upper_bound(r={:?}={})" ,
717
+ r,
718
+ inferred_values. region_value_str( r)
719
+ ) ;
720
+
721
+ let lub = self . universal_upper_bound ( r) ;
722
+
723
+ // Grow further to get smallest universal region known to
724
+ // creator.
725
+ let non_local_lub = self . universal_regions . non_local_upper_bound ( lub) ;
726
+
727
+ debug ! (
728
+ "non_local_universal_upper_bound: non_local_lub={:?}" ,
729
+ non_local_lub
730
+ ) ;
731
+
732
+ non_local_lub
733
+ }
734
+
735
+ /// Returns a universally quantified region that outlives the
736
+ /// value of `r` (`r` may be existentially or universally
737
+ /// quantified).
738
+ ///
666
739
/// Since `r` is (potentially) an existential region, it has some
667
740
/// value which may include (a) any number of points in the CFG
668
741
/// and (b) any number of `end('x)` elements of universally
@@ -673,15 +746,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
673
746
/// include the CFG anyhow.
674
747
/// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding
675
748
/// a result `'y`.
676
- /// - Finally, we take the non-local upper bound of `'y`.
677
- /// - This uses `UniversalRegions::non_local_upper_bound`, which
678
- /// is similar to this method but only works on universal
679
- /// regions).
680
- fn non_local_universal_upper_bound ( & self , r : RegionVid ) -> RegionVid {
749
+ fn universal_upper_bound ( & self , r : RegionVid ) -> RegionVid {
681
750
let inferred_values = self . inferred_values . as_ref ( ) . unwrap ( ) ;
682
751
683
752
debug ! (
684
- "non_local_universal_upper_bound (r={:?}={})" ,
753
+ "universal_upper_bound (r={:?}={})" ,
685
754
r,
686
755
inferred_values. region_value_str( r)
687
756
) ;
@@ -693,18 +762,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
693
762
lub = self . universal_regions . postdom_upper_bound ( lub, ur) ;
694
763
}
695
764
696
- debug ! ( "non_local_universal_upper_bound: lub={:?}" , lub) ;
697
-
698
- // Grow further to get smallest universal region known to
699
- // creator.
700
- let non_local_lub = self . universal_regions . non_local_upper_bound ( lub) ;
765
+ debug ! ( "universal_upper_bound: r={:?} lub={:?}" , r, lub) ;
701
766
702
- debug ! (
703
- "non_local_universal_upper_bound: non_local_lub={:?}" ,
704
- non_local_lub
705
- ) ;
706
-
707
- non_local_lub
767
+ lub
708
768
}
709
769
710
770
/// Test if `test` is true when applied to `lower_bound` at
@@ -924,8 +984,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
924
984
) {
925
985
// Obviously uncool error reporting.
926
986
927
- let fr_name = self . definitions [ fr ] . external_name ;
928
- let outlived_fr_name = self . definitions [ outlived_fr] . external_name ;
987
+ let fr_name = self . to_error_region ( fr ) ;
988
+ let outlived_fr_name = self . to_error_region ( outlived_fr) ;
929
989
930
990
if let ( Some ( f) , Some ( o) ) = ( fr_name, outlived_fr_name) {
931
991
let tables = infcx. tcx . typeck_tables_of ( mir_def_id) ;
0 commit comments