Skip to content

Commit 95f24cc

Browse files
committed
temp
1 parent 29d69ac commit 95f24cc

File tree

1 file changed

+144
-109
lines changed

1 file changed

+144
-109
lines changed

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+144-109
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,87 @@ impl<'tcx> BorrowCheckRootCtxt<'tcx> {
6262
constraints,
6363
deferred_opaque_type_errors,
6464
universal_region_relations,
65-
Rc::clone(location_map),
65+
location_map,
6666
)
6767
}
6868
}
6969

70+
struct RegionCtxt<'a, 'tcx> {
71+
infcx: &'a BorrowckInferCtxt<'tcx>,
72+
definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
73+
universal_region_relations: &'a UniversalRegionRelations<'tcx>,
74+
constraint_sccs: ConstraintSccs,
75+
rev_scc_graph: ReverseSccGraph,
76+
scc_values: RegionValues<ConstraintSccIndex>,
77+
}
78+
79+
impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
80+
fn new(
81+
infcx: &'a BorrowckInferCtxt<'tcx>,
82+
universal_region_relations: &'a Frozen<UniversalRegionRelations<'tcx>>,
83+
location_map: Rc<DenseLocationMap>,
84+
constraints: &MirTypeckRegionConstraints<'tcx>,
85+
) -> RegionCtxt<'a, 'tcx> {
86+
let mut definitions: IndexVec<_, _> = infcx
87+
.get_region_var_infos()
88+
.iter()
89+
.map(|info| RegionDefinition::new(info.universe, info.origin))
90+
.collect();
91+
92+
for (external_name, variable) in
93+
universal_region_relations.universal_regions.named_universal_regions_iter()
94+
{
95+
definitions[variable].external_name = Some(external_name);
96+
}
97+
98+
let universal_regions = &universal_region_relations.universal_regions;
99+
let fr_static = universal_regions.fr_static;
100+
let constraint_sccs =
101+
constraints.outlives_constraints.compute_sccs(fr_static, &definitions);
102+
let rev_scc_graph = ReverseSccGraph::compute(&constraint_sccs, universal_regions);
103+
// Unlike the `RegionInferenceContext`, we only care about free regions
104+
// and fully ignore liveness and placeholders.
105+
let placeholder_indices = Default::default();
106+
let mut scc_values =
107+
RegionValues::new(location_map, universal_regions.len(), placeholder_indices);
108+
for variable in definitions.indices() {
109+
let scc = constraint_sccs.scc(variable);
110+
match definitions[variable].origin {
111+
NllRegionVariableOrigin::FreeRegion => {
112+
scc_values.add_element(scc, variable);
113+
}
114+
_ => {}
115+
}
116+
}
117+
scc_values.propagate_constraints(&constraint_sccs);
118+
119+
RegionCtxt {
120+
infcx,
121+
definitions,
122+
universal_region_relations,
123+
constraint_sccs,
124+
rev_scc_graph,
125+
scc_values,
126+
}
127+
}
128+
129+
fn representative(&self, vid: RegionVid) -> RegionVid {
130+
self.constraint_sccs.scc(vid);
131+
rcx.constraint_sccs.annotation(scc).representative
132+
}
133+
134+
fn universal_regions(&self) -> &UniversalRegions<'tcx> {
135+
&self.universal_region_relations.universal_regions
136+
}
137+
}
138+
70139
pub(crate) fn handle_opaque_type_uses<'tcx>(
71140
root_cx: &mut BorrowCheckRootCtxt<'tcx>,
72141
infcx: &BorrowckInferCtxt<'tcx>,
73142
constraints: &mut MirTypeckRegionConstraints<'tcx>,
74143
deferred_errors: &mut Vec<DeferredOpaqueTypeError<'tcx>>,
75144
universal_region_relations: &Frozen<UniversalRegionRelations<'tcx>>,
76-
location_map: Rc<DenseLocationMap>,
145+
location_map: &Rc<DenseLocationMap>,
77146
) {
78147
let opaque_types = infcx.take_opaque_types();
79148
if opaque_types.is_empty() {
@@ -97,114 +166,82 @@ pub(crate) fn handle_opaque_type_uses<'tcx>(
97166
})
98167
.collect::<Vec<_>>();
99168

100-
let mut definitions: IndexVec<_, _> = infcx
101-
.get_region_var_infos()
102-
.iter()
103-
.map(|info| RegionDefinition::new(info.universe, info.origin))
104-
.collect();
105-
106-
// Update the names (if any)
107-
// This iterator has unstable order but we collect it all into an IndexVec
108-
for (external_name, variable) in
109-
universal_region_relations.universal_regions.named_universal_regions_iter()
110-
{
111-
definitions[variable].external_name = Some(external_name);
112-
}
169+
collect_defining_uses(
170+
root_cx,
171+
infcx,
172+
constraints,
173+
deferred_errors,
174+
universal_region_relations,
175+
location_map,
176+
&mut opaque_types,
177+
);
178+
179+
apply_defining_uses(root_cx, infcx, constraints, universal_region_relations, &opaque_types);
180+
}
113181

114-
let universal_regions = &universal_region_relations.universal_regions;
115-
let fr_static = universal_regions.fr_static;
116-
let constraint_sccs = &constraints.outlives_constraints.compute_sccs(fr_static, &definitions);
117-
let rev_scc_graph = &ReverseSccGraph::compute(&constraint_sccs, universal_regions);
118-
// Unlike the `RegionInferenceContext`, we only care about free regions
119-
// and fully ignore liveness and placeholders.
120-
let placeholder_indices = Default::default();
121-
let mut scc_values =
122-
RegionValues::new(location_map, universal_regions.len(), placeholder_indices);
123-
for variable in definitions.indices() {
124-
let scc = constraint_sccs.scc(variable);
125-
match definitions[variable].origin {
126-
NllRegionVariableOrigin::FreeRegion => {
127-
scc_values.add_element(scc, variable);
128-
}
129-
_ => {}
130-
}
131-
}
132-
scc_values.propagate_constraints(&constraint_sccs);
133-
for entry in &mut opaque_types {
134-
// Map all opaque types to their SCC representatives.
135-
*entry = fold_regions(tcx, *entry, |r, _| {
136-
let scc = constraint_sccs.scc(r.as_var());
137-
let vid = constraint_sccs.annotation(scc).representative;
138-
Region::new_var(tcx, vid)
139-
})
140-
}
182+
fn collect_defining_uses<'tcx>(
183+
root_cx: &mut BorrowCheckRootCtxt<'tcx>,
184+
infcx: &BorrowckInferCtxt<'tcx>,
185+
constraints: &mut MirTypeckRegionConstraints<'tcx>,
186+
deferred_errors: &mut Vec<DeferredOpaqueTypeError<'tcx>>,
187+
universal_region_relations: &Frozen<UniversalRegionRelations<'tcx>>,
188+
location_map: &Rc<DenseLocationMap>,
189+
opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
190+
) {
191+
let tcx = infcx.tcx;
192+
let rcx = RegionCtxt::new(infcx, universal_region_relations, Rc::clone(location_map), constraints);
141193

142-
// We start by looking for defining uses of the opaque. These are uses where all arguments
143-
// of the opaque are free regions. We apply "member constraints" to its hidden region and
144-
// map the hidden type to the definition site of the opaque.
145-
'entry: for &(opaque_type_key, hidden_type) in &opaque_types {
194+
let mut defining_uses = vec![];
195+
'all_uses: for &(opaque_type_key, hidden_type) in opaque_types {
146196
// Check whether the arguments are fully universal.
147197
//
148198
// FIXME: We currently treat `Opaque<'a, 'a>` as a defining use and then emit an error
149199
// as it's not fully universal. We should share this code with `check_opaque_type_parameter_valid`
150200
// to only consider actual defining uses as defining.
151-
let mut arg_regions = vec![(universal_regions.fr_static, tcx.lifetimes.re_static)];
201+
let mut arg_regions = vec![(rcx.universal_regions().fr_static, tcx.lifetimes.re_static)];
152202
for (_idx, captured_arg) in opaque_type_key.iter_captured_args(tcx) {
153-
if let Some(region) = captured_arg.as_region() {
154-
let vid = region.as_var();
155-
if matches!(definitions[vid].origin, NllRegionVariableOrigin::FreeRegion)
156-
&& !matches!(
157-
universal_regions.region_classification(vid),
158-
Some(RegionClassification::External)
159-
)
160-
{
161-
arg_regions.push((vid, definitions[vid].external_name.unwrap()));
203+
if let Some(r) = captured_arg.as_region() {
204+
let vid = rcx.representative(r.as_var());
205+
let is_non_external_free_region =
206+
matches!(rcx.definitions[vid].origin, NllRegionVariableOrigin::FreeRegion)
207+
&& !matches!(
208+
rcx.universal_regions().region_classification(vid),
209+
Some(RegionClassification::External)
210+
);
211+
212+
if is_non_external_free_region {
213+
arg_regions.push((vid, rcx.definitions[vid].external_name.unwrap()));
162214
} else {
163-
continue 'entry;
215+
continue 'all_uses;
164216
}
165217
}
166218
}
167219

168-
debug!(?opaque_type_key, ?hidden_type, "check defining use");
169-
170-
let opaque_type_key = opaque_type_key.fold_captured_lifetime_args(tcx, |region| {
171-
let vid = region.as_var();
172-
assert!(matches!(definitions[vid].origin, NllRegionVariableOrigin::FreeRegion));
173-
definitions[vid].external_name.unwrap()
174-
});
220+
defining_uses.push((opaque_type_key, arg_regions, hidden_type))
221+
}
175222

176-
let hidden_type = hidden_type.fold_with(&mut OpaqueHiddenTypeFolder {
177-
infcx,
223+
debug!(?defining_uses);
178224

179-
opaque_type_key,
180-
hidden_type,
181-
deferred_errors,
225+
apply_member_constraints();
182226

183-
arg_regions: &arg_regions,
184-
universal_region_relations,
185-
constraint_sccs,
186-
rev_scc_graph,
187-
scc_values: &scc_values,
188-
});
189-
190-
let ty = infcx
191-
.infer_opaque_definition_from_instantiation(opaque_type_key, hidden_type)
192-
.unwrap_or_else(|err| {
193-
deferred_errors.push(DeferredOpaqueTypeError::InvalidOpaqueTypeArgs(err));
194-
Ty::new_error_with_message(
195-
tcx,
196-
hidden_type.span,
197-
"deferred invalid opaque type args",
198-
)
199-
});
200-
201-
root_cx.add_concrete_opaque_type(
202-
opaque_type_key.def_id,
203-
OpaqueHiddenType { span: hidden_type.span, ty },
204-
);
205-
}
227+
// Applying member constraints may add new region constraints, so we
228+
// need to recompute the region context before actually mapping the defining
229+
// uses to the definition site.
230+
//
231+
// FIXME: We should be able to partially reuse and optimize this.
232+
let rcx = RegionCtxt::new(infcx, universal_region_relations, Rc::clone(location_map), constraints)
233+
map_defining_uses_to_definition_site();
234+
}
206235

207-
for &(key, hidden_type) in &opaque_types {
236+
fn apply_defining_uses<'tcx>(
237+
root_cx: &mut BorrowCheckRootCtxt<'tcx>,
238+
infcx: &BorrowckInferCtxt<'tcx>,
239+
constraints: &mut MirTypeckRegionConstraints<'tcx>,
240+
universal_region_relations: &Frozen<UniversalRegionRelations<'tcx>>,
241+
opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
242+
) {
243+
let tcx = infcx.tcx;
244+
for &(key, hidden_type) in opaque_types {
208245
let Some(expected) = root_cx.get_concrete_opaque_type(key.def_id) else {
209246
let guar =
210247
tcx.dcx().span_err(hidden_type.span, "non-defining use in the defining scope");
@@ -223,6 +260,7 @@ pub(crate) fn handle_opaque_type_uses<'tcx>(
223260
}
224261
});
225262

263+
let universal_regions = &universal_region_relations.universal_regions;
226264
let mut relation =
227265
EquateRegions { infcx, span: hidden_type.span, universal_regions, constraints };
228266
match TypeRelation::relate(&mut relation, hidden_type.ty, expected.ty) {
@@ -259,23 +297,20 @@ fn to_region_vid<'tcx>(
259297
}
260298

261299
struct OpaqueHiddenTypeFolder<'a, 'tcx> {
262-
infcx: &'a BorrowckInferCtxt<'tcx>,
300+
rcx: &'a RegionCtxt<'a, 'tcx>,
301+
263302
// For diagnostics.
264303
opaque_type_key: OpaqueTypeKey<'tcx>,
265304
hidden_type: OpaqueHiddenType<'tcx>,
266305
deferred_errors: &'a mut Vec<DeferredOpaqueTypeError<'tcx>>,
267306

268307
arg_regions: &'a [(RegionVid, Region<'tcx>)],
269-
universal_region_relations: &'a UniversalRegionRelations<'tcx>,
270-
constraint_sccs: &'a ConstraintSccs,
271-
rev_scc_graph: &'a ReverseSccGraph,
272-
scc_values: &'a RegionValues<ConstraintSccIndex>,
273308
}
274309

275310
impl<'tcx> OpaqueHiddenTypeFolder<'_, 'tcx> {
276311
#[instrument(level = "debug", skip(self))]
277312
fn apply_member_constraint(&mut self, member_vid: RegionVid) -> Option<Region<'tcx>> {
278-
let member = self.constraint_sccs.scc(member_vid);
313+
let member = self.rcx.constraint_sccs.scc(member_vid);
279314
if let Some((_, reg)) = self.arg_regions.iter().copied().find(|&(vid, _)| vid == member_vid)
280315
{
281316
debug!("member equal to arg");
@@ -284,7 +319,7 @@ impl<'tcx> OpaqueHiddenTypeFolder<'_, 'tcx> {
284319

285320
// If the member region lives in a higher universe, we currently choose
286321
// the most conservative option by leaving it unchanged.
287-
if !self.constraint_sccs.annotation(member).min_universe().is_root() {
322+
if !self.rcx.constraint_sccs.annotation(member).min_universe().is_root() {
288323
debug!("member not in root universe");
289324
return None;
290325
}
@@ -297,8 +332,8 @@ impl<'tcx> OpaqueHiddenTypeFolder<'_, 'tcx> {
297332
.iter()
298333
.copied()
299334
.filter(|&(choice_region, _)| {
300-
self.scc_values.universal_regions_outlived_by(member).all(|lower_bound| {
301-
self.universal_region_relations.outlives(choice_region, lower_bound)
335+
self.rcx.scc_values.universal_regions_outlived_by(member).all(|lower_bound| {
336+
self.rcx.universal_region_relations.outlives(choice_region, lower_bound)
302337
})
303338
})
304339
.collect::<Vec<_>>();
@@ -312,9 +347,9 @@ impl<'tcx> OpaqueHiddenTypeFolder<'_, 'tcx> {
312347
// If we have a requirement `'upper_bound: 'member`, equating `'member`
313348
// with some region `'choice` means we now also require `'upper_bound: 'choice`.
314349
// Avoid choice regions for which this does not hold.
315-
for ub in self.rev_scc_graph.upper_bounds(member) {
350+
for ub in self.rcx.rev_scc_graph.upper_bounds(member) {
316351
choice_regions.retain(|&(choice_region, _)| {
317-
self.universal_region_relations.outlives(ub, choice_region)
352+
self.rcx.universal_region_relations.outlives(ub, choice_region)
318353
});
319354
}
320355

@@ -333,14 +368,14 @@ impl<'tcx> OpaqueHiddenTypeFolder<'_, 'tcx> {
333368
// `['d, 'e]` are ignored because they do not compare - the same goes for `['a, 'b]`.
334369
let totally_ordered_subset = choice_regions.iter().copied().filter(|&(r1, _)| {
335370
choice_regions.iter().all(|&(r2, _)| {
336-
self.universal_region_relations.outlives(r1, r2)
337-
|| self.universal_region_relations.outlives(r2, r1)
371+
self.rcx.universal_region_relations.outlives(r1, r2)
372+
|| self.rcx.universal_region_relations.outlives(r2, r1)
338373
})
339374
});
340375
// Now we're left with `['static, 'c]`. Pick `'c` as the minimum!
341376
let Some((_, min_choice)) = totally_ordered_subset.reduce(|(r1, r1_reg), (r2, r2_reg)| {
342-
let r1_outlives_r2 = self.universal_region_relations.outlives(r1, r2);
343-
let r2_outlives_r1 = self.universal_region_relations.outlives(r2, r1);
377+
let r1_outlives_r2 = self.rcx.universal_region_relations.outlives(r1, r2);
378+
let r2_outlives_r1 = self.rcx.universal_region_relations.outlives(r2, r1);
344379
match (r1_outlives_r2, r2_outlives_r1) {
345380
(true, true) => {
346381
if r1 < r2 {
@@ -379,7 +414,7 @@ impl<'tcx> OpaqueHiddenTypeFolder<'_, 'tcx> {
379414

380415
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueHiddenTypeFolder<'_, 'tcx> {
381416
fn cx(&self) -> TyCtxt<'tcx> {
382-
self.infcx.tcx
417+
self.rcx.infcx.tcx
383418
}
384419

385420
fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {

0 commit comments

Comments
 (0)