Skip to content

Commit a5c71c7

Browse files
committed
Avoid handling placeholders for MIR bodies without them
1 parent a800d70 commit a5c71c7

File tree

3 files changed

+122
-29
lines changed

3 files changed

+122
-29
lines changed

compiler/rustc_borrowck/src/constraints/mod.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ use std::fmt;
22
use std::ops::Index;
33

44
use rustc_data_structures::fx::FxHashSet;
5+
use rustc_data_structures::graph::scc;
56
use rustc_index::{IndexSlice, IndexVec};
67
use rustc_infer::infer::NllRegionVariableOrigin;
78
use rustc_middle::mir::ConstraintCategory;
89
use rustc_middle::ty::{RegionVid, TyCtxt, VarianceDiagInfo};
910
use rustc_span::Span;
1011
use tracing::{debug, instrument};
1112

12-
use crate::region_infer::{ConstraintSccs, RegionDefinition, RegionTracker};
13+
use crate::region_infer::{PlaceholderTracking, RegionDefinition, RegionTracker};
1314
use crate::type_check::Locations;
1415
use crate::universal_regions::UniversalRegions;
1516

@@ -59,16 +60,15 @@ impl<'tcx> OutlivesConstraintSet<'tcx> {
5960
/// Computes cycles (SCCs) in the graph of regions. In particular,
6061
/// find all regions R1, R2 such that R1: R2 and R2: R1 and group
6162
/// them into an SCC, and find the relationships between SCCs.
62-
pub(crate) fn compute_sccs(
63+
pub(crate) fn compute_sccs<A: scc::Annotation, F: Fn(RegionVid) -> A>(
6364
&self,
6465
static_region: RegionVid,
6566
definitions: &IndexVec<RegionVid, RegionDefinition<'tcx>>,
66-
) -> ConstraintSccs {
67+
annotate_region: F,
68+
) -> scc::Sccs<RegionVid, ConstraintSccIndex, A> {
6769
let constraint_graph = self.graph(definitions.len());
6870
let region_graph = &constraint_graph.region_graph(self, static_region);
69-
ConstraintSccs::new_with_annotation(&region_graph, |r| {
70-
RegionTracker::new(r, &definitions[r])
71-
})
71+
scc::Sccs::new_with_annotation(&region_graph, annotate_region)
7272
}
7373

7474
/// There is a placeholder violation; add a requirement
@@ -131,9 +131,11 @@ impl<'tcx> OutlivesConstraintSet<'tcx> {
131131
&mut self,
132132
universal_regions: &UniversalRegions<'tcx>,
133133
definitions: &IndexVec<RegionVid, RegionDefinition<'tcx>>,
134-
) -> ConstraintSccs {
134+
) -> scc::Sccs<RegionVid, ConstraintSccIndex, PlaceholderTracking> {
135135
let fr_static = universal_regions.fr_static;
136-
let sccs = self.compute_sccs(fr_static, definitions);
136+
let new_tracker = |r| PlaceholderTracking::On(RegionTracker::new(r, &definitions[r]));
137+
138+
let sccs = self.compute_sccs(fr_static, definitions, new_tracker);
137139

138140
// Is this SCC already outliving static directly or transitively?
139141
let mut outlives_static = FxHashSet::default();
@@ -200,7 +202,7 @@ impl<'tcx> OutlivesConstraintSet<'tcx> {
200202
if !outlives_static.is_empty() {
201203
debug!("The following SCCs had :'static constraints added: {:?}", outlives_static);
202204
// We changed the constraint set and so must recompute SCCs.
203-
self.compute_sccs(fr_static, definitions)
205+
self.compute_sccs(fr_static, definitions, new_tracker)
204206
} else {
205207
// If we didn't add any back-edges; no more work needs doing
206208
sccs

compiler/rustc_borrowck/src/region_infer/mod.rs

+111-12
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,89 @@ mod reverse_sccs;
4646

4747
pub(crate) mod values;
4848

49-
pub(crate) type ConstraintSccs = Sccs<RegionVid, ConstraintSccIndex, RegionTracker>;
49+
pub(crate) type ConstraintSccs = Sccs<RegionVid, ConstraintSccIndex, PlaceholderTracking>;
50+
51+
#[derive(Copy, Clone, Debug)]
52+
pub enum PlaceholderTracking {
53+
Off(Representative),
54+
On(RegionTracker),
55+
}
56+
57+
impl scc::Annotation for PlaceholderTracking {
58+
fn merge_scc(self, other: Self) -> Self {
59+
use PlaceholderTracking::*;
60+
61+
match (self, other) {
62+
(Off(this), Off(that)) => Off(this.merge_scc(that)),
63+
(On(this), On(that)) => On(this.merge_scc(that)),
64+
_ => unreachable!(),
65+
}
66+
}
67+
68+
fn merge_reached(self, other: Self) -> Self {
69+
use PlaceholderTracking::*;
70+
71+
match (self, other) {
72+
(Off(this), Off(that)) => Off(this.merge_reached(that)),
73+
(On(this), On(that)) => On(this.merge_reached(that)),
74+
_ => unreachable!(),
75+
}
76+
}
77+
}
78+
79+
impl PlaceholderTracking {
80+
pub(crate) fn representative_rvid(&self) -> RegionVid {
81+
match self {
82+
PlaceholderTracking::Off(r) => r.rvid(),
83+
PlaceholderTracking::On(region_tracker) => region_tracker.representative_rvid(),
84+
}
85+
}
86+
87+
pub(crate) fn reaches_other_placeholder(&self, other: RegionVid) -> Option<RegionVid> {
88+
match self {
89+
PlaceholderTracking::Off(_) => None,
90+
PlaceholderTracking::On(region_tracker) => {
91+
region_tracker.reaches_other_placeholder(other)
92+
}
93+
}
94+
}
95+
96+
pub(crate) fn universe_violation(&self) -> Option<RegionVid> {
97+
match self {
98+
PlaceholderTracking::Off(_) => None,
99+
PlaceholderTracking::On(region_tracker) => region_tracker.universe_violation(),
100+
}
101+
}
102+
103+
fn min_universe(&self) -> UniverseIndex {
104+
match self {
105+
PlaceholderTracking::Off(_) => UniverseIndex::ROOT, // Not technically correct?
106+
PlaceholderTracking::On(region_tracker) => region_tracker.min_universe(),
107+
}
108+
}
109+
110+
fn universe_compatible_with(&self, other: PlaceholderTracking) -> bool {
111+
use PlaceholderTracking::*;
112+
match (self, other) {
113+
(Off(_), Off(_)) => true, // Not technically correct?
114+
(On(this), On(that)) => this.universe_compatible_with(that),
115+
_ => unreachable!(),
116+
}
117+
}
118+
119+
fn placeholder_representative(&self) -> Option<RegionVid> {
120+
match self {
121+
PlaceholderTracking::Off(_) => None,
122+
PlaceholderTracking::On(region_tracker) => region_tracker.placeholder_representative(),
123+
}
124+
}
125+
}
50126

51127
/// The representative region variable for an SCC, tagged by its origin.
52128
/// We prefer placeholders over existentially quantified variables, otherwise
53129
/// it's the one with the smallest Region Variable ID.
54130
#[derive(Copy, Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
55-
enum Representative {
131+
pub enum Representative {
56132
FreeRegion(RegionVid),
57133
Placeholder(RegionVid),
58134
Existential(RegionVid),
@@ -66,6 +142,14 @@ impl Representative {
66142
Representative::Existential(region_vid) => *region_vid,
67143
}
68144
}
145+
146+
fn new(r: RegionVid, definitions: &IndexVec<RegionVid, RegionDefinition<'_>>) -> Self {
147+
match definitions[r].origin {
148+
NllRegionVariableOrigin::FreeRegion => Representative::FreeRegion(r),
149+
NllRegionVariableOrigin::Placeholder(_) => Representative::Placeholder(r),
150+
NllRegionVariableOrigin::Existential { .. } => Representative::Existential(r),
151+
}
152+
}
69153
}
70154

71155
impl scc::Annotation for Representative {
@@ -457,7 +541,10 @@ pub(crate) enum ExtraConstraintInfo {
457541
}
458542

459543
#[instrument(skip(infcx, sccs), level = "debug")]
460-
fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) {
544+
fn sccs_info<'tcx, A: scc::Annotation>(
545+
infcx: &BorrowckInferCtxt<'tcx>,
546+
sccs: &scc::Sccs<RegionVid, ConstraintSccIndex, A>,
547+
) {
461548
use crate::renumber::RegionCtxt;
462549

463550
let var_to_origin = infcx.reg_var_to_origin.borrow();
@@ -544,27 +631,39 @@ impl<'tcx> RegionInferenceContext<'tcx> {
544631
debug!("type tests: {:#?}", type_tests);
545632

546633
// Create a RegionDefinition for each inference variable.
547-
let definitions = {
548-
let mut definitions: IndexVec<_, _> = var_infos
549-
.iter()
550-
.map(|info| RegionDefinition::new(info.universe, info.origin))
551-
.collect();
634+
let (definitions, has_placeholders) = {
635+
let mut definitions = IndexVec::with_capacity(var_infos.len());
636+
let mut has_placeholders = false;
637+
638+
for info in var_infos.iter() {
639+
let definition = RegionDefinition::new(info.universe, info.origin);
640+
has_placeholders |=
641+
matches!(definition.origin, NllRegionVariableOrigin::Placeholder(_));
642+
definitions.push(definition);
643+
}
552644

553645
// Add external names from universal regions in fun function definitions.
554646
for (external_name, variable) in universal_regions.named_universal_regions() {
555647
debug!("region {:?} has external name {:?}", variable, external_name);
556648
definitions[variable].external_name = Some(external_name);
557649
}
558-
definitions
650+
(definitions, has_placeholders)
559651
};
560652

561-
let constraint_sccs =
562-
outlives_constraints.add_outlives_static(&universal_regions, &definitions);
653+
let constraint_sccs = if has_placeholders {
654+
debug!("Placeholders present; activating placeholder handling logic!");
655+
outlives_constraints.add_outlives_static(&universal_regions, &definitions)
656+
} else {
657+
debug!("No placeholders in MIR body; disabling their validation.");
658+
outlives_constraints.compute_sccs(universal_regions.fr_static, &definitions, |r| {
659+
PlaceholderTracking::Off(Representative::new(r, &definitions))
660+
})
661+
};
563662
let constraints = Frozen::freeze(outlives_constraints);
564663
let constraint_graph = Frozen::freeze(constraints.graph(definitions.len()));
565664

566665
if cfg!(debug_assertions) {
567-
sccs_info(infcx, &constraint_sccs);
666+
sccs_info(infcx, &constraint_sccs)
568667
}
569668

570669
let mut scc_values = RegionValues::new(elements, universal_regions.len());

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

-8
Original file line numberDiff line numberDiff line change
@@ -216,14 +216,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
216216
let higher_ranked_region = if let Some(representative) =
217217
self.placeholder_representative(scc)
218218
{
219-
// FIXME: remove this assertion once the tests pass!
220-
assert!(
221-
self.constraint_sccs
222-
.annotation(scc)
223-
.placeholder_representative()
224-
.is_some_and(|representative| representative == vid)
225-
);
226-
227219
ty::Region::new_placeholder(tcx, representative)
228220
} else {
229221
debug!(

0 commit comments

Comments
 (0)