@@ -13,12 +13,12 @@ use rustc_infer::infer::RegionVariableOrigin;
13
13
use rustc_middle:: bug;
14
14
use rustc_middle:: mir:: ConstraintCategory ;
15
15
use rustc_middle:: ty:: { RegionVid , UniverseIndex } ;
16
- use tracing:: { debug, trace} ;
16
+ use tracing:: { debug, instrument , trace} ;
17
17
18
18
use crate :: constraints:: graph:: { ConstraintGraph , Normal , RegionGraph } ;
19
19
use crate :: constraints:: { ConstraintSccIndex , OutlivesConstraintSet } ;
20
20
use crate :: consumers:: OutlivesConstraint ;
21
- use crate :: diagnostics:: UniverseInfo ;
21
+ use crate :: diagnostics:: { RegionErrorKind , RegionErrors , UniverseInfo } ;
22
22
use crate :: member_constraints:: MemberConstraintSet ;
23
23
use crate :: region_infer:: values:: { LivenessValues , PlaceholderIndices } ;
24
24
use crate :: region_infer:: { ConstraintSccs , RegionDefinition , Representative , TypeTest } ;
@@ -293,6 +293,7 @@ pub(crate) fn compute_sccs_applying_placeholder_outlives_constraints<'tcx>(
293
293
constraints : MirTypeckRegionConstraints < ' tcx > ,
294
294
universal_region_relations : & Frozen < UniversalRegionRelations < ' tcx > > ,
295
295
infcx : & BorrowckInferCtxt < ' tcx > ,
296
+ errors_buffer : & mut RegionErrors < ' tcx > ,
296
297
) -> LoweredConstraints < ' tcx > {
297
298
let universal_regions = & universal_region_relations. universal_regions ;
298
299
let ( definitions, has_placeholders) = region_definitions ( universal_regions, infcx) ;
@@ -359,6 +360,13 @@ pub(crate) fn compute_sccs_applying_placeholder_outlives_constraints<'tcx>(
359
360
& definitions,
360
361
) ;
361
362
363
+ find_placeholder_mismatch_errors (
364
+ & definitions,
365
+ & constraint_sccs,
366
+ & scc_annotations,
367
+ errors_buffer,
368
+ ) ;
369
+
362
370
let ( constraint_sccs, scc_annotations) = if added_constraints {
363
371
let mut annotations = SccAnnotations :: init ( & definitions) ;
364
372
@@ -510,3 +518,65 @@ fn find_region<'tcx>(
510
518
// so if we don't find what we are looking for there's a bug somwehere.
511
519
bug ! ( "Should have found something!" ) ;
512
520
}
521
+
522
+ /// Identify errors where placeholders illegally reach other regions, and generate
523
+ /// errors stored into `errors_buffer`.
524
+ ///
525
+ /// There are two sources of such errors:
526
+ /// 1. A placeholder reaches (possibly transitively) another placeholder.
527
+ /// 2. A placeholder `p` reaches (possibly transitively) an existential `e`,
528
+ /// where `e` has an allowed maximum universe smaller than `p`'s.
529
+ ///
530
+ /// There are other potential placeholder errors, but those are detected after
531
+ /// region inference, since it may apply type tests or member constraints that
532
+ /// alter the contents of SCCs and thus can't be detected at this point.
533
+ #[ instrument( skip( definitions, sccs, annotations, errors_buffer) , level = "debug" ) ]
534
+ fn find_placeholder_mismatch_errors < ' tcx > (
535
+ definitions : & IndexVec < RegionVid , RegionDefinition < ' tcx > > ,
536
+ sccs : & Sccs < RegionVid , ConstraintSccIndex > ,
537
+ annotations : & SccAnnotations < ' _ , ' _ , RegionTracker > ,
538
+ errors_buffer : & mut RegionErrors < ' tcx > ,
539
+ ) {
540
+ use NllRegionVariableOrigin :: Placeholder ;
541
+ for ( rvid, definition) in definitions. iter_enumerated ( ) {
542
+ let Placeholder ( origin_a) = definition. origin else {
543
+ continue ;
544
+ } ;
545
+
546
+ let scc = sccs. scc ( rvid) ;
547
+ let annotation = annotations. scc_to_annotation [ scc] ;
548
+
549
+ if let Some ( existental_that_cannot_name_rvid) =
550
+ annotation. reaches_existential_that_cannot_name_us ( )
551
+ {
552
+ errors_buffer. push ( RegionErrorKind :: PlaceholderReachesExistentialThatCannotNameIt {
553
+ longer_fr : rvid,
554
+ existental_that_cannot_name_longer : existental_that_cannot_name_rvid,
555
+ placeholder : origin_a,
556
+ } )
557
+ }
558
+
559
+ let Some ( other_placeholder) = annotation. reaches_other_placeholder ( rvid) else {
560
+ trace ! ( "{rvid:?} reaches no other placeholders" ) ;
561
+ continue ;
562
+ } ;
563
+
564
+ debug ! (
565
+ "Placeholder {rvid:?} of SCC {scc:?} reaches other placeholder {other_placeholder:?}"
566
+ ) ;
567
+
568
+ // FIXME SURELY there is a neater way to do this?
569
+ let Placeholder ( origin_b) = definitions[ other_placeholder] . origin else {
570
+ unreachable ! (
571
+ "Region {rvid:?}, {other_placeholder:?} should be placeholders but aren't!"
572
+ ) ;
573
+ } ;
574
+
575
+ errors_buffer. push ( RegionErrorKind :: PlaceholderMismatch {
576
+ rvid_a : rvid,
577
+ rvid_b : other_placeholder,
578
+ origin_a,
579
+ origin_b,
580
+ } ) ;
581
+ }
582
+ }
0 commit comments