Skip to content

Commit 298629b

Browse files
committed
handle opaque types before region inference
1 parent e88f7d2 commit 298629b

40 files changed

+976
-1233
lines changed

compiler/rustc_borrowck/src/dataflow.rs

Lines changed: 2 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::fmt;
22

33
use rustc_data_structures::fx::FxIndexMap;
4-
use rustc_data_structures::graph;
54
use rustc_index::bit_set::{DenseBitSet, MixedBitSet};
65
use rustc_middle::mir::{
76
self, BasicBlock, Body, CallReturnPlaces, Location, Place, TerminatorEdges,
@@ -317,9 +316,8 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
317316
loans_out_of_scope_at_location: FxIndexMap::default(),
318317
};
319318
for (loan_idx, loan_data) in borrow_set.iter_enumerated() {
320-
let issuing_region = loan_data.region;
321319
let loan_issued_at = loan_data.reserve_location;
322-
prec.precompute_loans_out_of_scope(loan_idx, issuing_region, loan_issued_at);
320+
prec.precompute_loans_out_of_scope(loan_idx, loan_issued_at);
323321
}
324322

325323
prec.loans_out_of_scope_at_location
@@ -328,45 +326,7 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
328326
/// Loans are in scope while they are live: whether they are contained within any live region.
329327
/// In the location-insensitive analysis, a loan will be contained in a region if the issuing
330328
/// region can reach it in the subset graph. So this is a reachability problem.
331-
fn precompute_loans_out_of_scope(
332-
&mut self,
333-
loan_idx: BorrowIndex,
334-
issuing_region: RegionVid,
335-
loan_issued_at: Location,
336-
) {
337-
let sccs = self.regioncx.constraint_sccs();
338-
let universal_regions = self.regioncx.universal_regions();
339-
340-
// The loop below was useful for the location-insensitive analysis but shouldn't be
341-
// impactful in the location-sensitive case. It seems that it does, however, as without it a
342-
// handful of tests fail. That likely means some liveness or outlives data related to choice
343-
// regions is missing
344-
// FIXME: investigate the impact of loans traversing applied member constraints and why some
345-
// tests fail otherwise.
346-
//
347-
// We first handle the cases where the loan doesn't go out of scope, depending on the
348-
// issuing region's successors.
349-
for successor in graph::depth_first_search(&self.regioncx.region_graph(), issuing_region) {
350-
// Via applied member constraints
351-
//
352-
// The issuing region can flow into the choice regions, and they are either:
353-
// - placeholders or free regions themselves,
354-
// - or also transitively outlive a free region.
355-
//
356-
// That is to say, if there are applied member constraints here, the loan escapes the
357-
// function and cannot go out of scope. We could early return here.
358-
//
359-
// For additional insurance via fuzzing and crater, we verify that the constraint's min
360-
// choice indeed escapes the function. In the future, we could e.g. turn this check into
361-
// a debug assert and early return as an optimization.
362-
let scc = sccs.scc(successor);
363-
for constraint in self.regioncx.applied_member_constraints(scc) {
364-
if universal_regions.is_universal_region(constraint.min_choice) {
365-
return;
366-
}
367-
}
368-
}
369-
329+
fn precompute_loans_out_of_scope(&mut self, loan_idx: BorrowIndex, loan_issued_at: Location) {
370330
let first_block = loan_issued_at.block;
371331
let first_bb_data = &self.body.basic_blocks[first_block];
372332

compiler/rustc_borrowck/src/diagnostics/opaque_types.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ use rustc_middle::mir::{self, ConstraintCategory, Location};
1313
use rustc_middle::ty::{
1414
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
1515
};
16+
use rustc_span::Span;
17+
use rustc_trait_selection::error_reporting::infer::region::unexpected_hidden_region_diagnostic;
1618
use rustc_trait_selection::errors::impl_trait_overcapture_suggestion;
1719

1820
use crate::MirBorrowckCtxt;
@@ -27,12 +29,46 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
2729
return;
2830
}
2931
let mut guar = None;
32+
let mut last_unexpected_hidden_region: Option<(Span, Ty<'_>, ty::OpaqueTypeKey<'tcx>)> =
33+
None;
3034
for error in errors {
3135
guar = Some(match error {
3236
DeferredOpaqueTypeError::InvalidOpaqueTypeArgs(err) => err.report(self.infcx),
3337
DeferredOpaqueTypeError::LifetimeMismatchOpaqueParam(err) => {
3438
self.infcx.dcx().emit_err(err)
3539
}
40+
DeferredOpaqueTypeError::UnexpectedHiddenRegion {
41+
opaque_type_key,
42+
hidden_type,
43+
member_region,
44+
} => {
45+
let named_ty = self
46+
.regioncx
47+
.name_regions_for_member_constraint(self.infcx.tcx, hidden_type.ty);
48+
let named_key = self
49+
.regioncx
50+
.name_regions_for_member_constraint(self.infcx.tcx, opaque_type_key);
51+
let named_region = self
52+
.regioncx
53+
.name_regions_for_member_constraint(self.infcx.tcx, member_region);
54+
let diag = unexpected_hidden_region_diagnostic(
55+
self.infcx,
56+
self.mir_def_id(),
57+
hidden_type.span,
58+
named_ty,
59+
named_region,
60+
named_key,
61+
);
62+
if last_unexpected_hidden_region
63+
!= Some((hidden_type.span, named_ty, named_key))
64+
{
65+
last_unexpected_hidden_region =
66+
Some((hidden_type.span, named_ty, named_key));
67+
diag.emit()
68+
} else {
69+
diag.delay_as_bug()
70+
}
71+
}
3672
});
3773
}
3874
let guar = guar.unwrap();

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use rustc_trait_selection::error_reporting::infer::nice_region_error::{
2323
self, HirTraitObjectVisitor, NiceRegionError, TraitObjectVisitor, find_anon_type,
2424
find_param_with_region, suggest_adding_lifetime_params,
2525
};
26-
use rustc_trait_selection::error_reporting::infer::region::unexpected_hidden_region_diagnostic;
2726
use rustc_trait_selection::infer::InferCtxtExt;
2827
use rustc_trait_selection::traits::{Obligation, ObligationCtxt};
2928
use tracing::{debug, instrument, trace};
@@ -105,18 +104,6 @@ pub(crate) enum RegionErrorKind<'tcx> {
105104
/// A generic bound failure for a type test (`T: 'a`).
106105
TypeTestError { type_test: TypeTest<'tcx> },
107106

108-
/// An unexpected hidden region for an opaque type.
109-
UnexpectedHiddenRegion {
110-
/// The span for the member constraint.
111-
span: Span,
112-
/// The hidden type.
113-
hidden_ty: Ty<'tcx>,
114-
/// The opaque type.
115-
key: ty::OpaqueTypeKey<'tcx>,
116-
/// The unexpected region.
117-
member_region: ty::Region<'tcx>,
118-
},
119-
120107
/// Higher-ranked subtyping error.
121108
BoundUniversalRegionError {
122109
/// The placeholder free region.
@@ -307,11 +294,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
307294
pub(crate) fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) {
308295
// Iterate through all the errors, producing a diagnostic for each one. The diagnostics are
309296
// buffered in the `MirBorrowckCtxt`.
310-
311297
let mut outlives_suggestion = OutlivesSuggestionBuilder::default();
312-
let mut last_unexpected_hidden_region: Option<(Span, Ty<'_>, ty::OpaqueTypeKey<'tcx>)> =
313-
None;
314-
315298
for (nll_error, _) in nll_errors.into_iter() {
316299
match nll_error {
317300
RegionErrorKind::TypeTestError { type_test } => {
@@ -362,30 +345,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
362345
}
363346
}
364347

365-
RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, key, member_region } => {
366-
let named_ty =
367-
self.regioncx.name_regions_for_member_constraint(self.infcx.tcx, hidden_ty);
368-
let named_key =
369-
self.regioncx.name_regions_for_member_constraint(self.infcx.tcx, key);
370-
let named_region = self
371-
.regioncx
372-
.name_regions_for_member_constraint(self.infcx.tcx, member_region);
373-
let diag = unexpected_hidden_region_diagnostic(
374-
self.infcx,
375-
self.mir_def_id(),
376-
span,
377-
named_ty,
378-
named_region,
379-
named_key,
380-
);
381-
if last_unexpected_hidden_region != Some((span, named_ty, named_key)) {
382-
self.buffer_error(diag);
383-
last_unexpected_hidden_region = Some((span, named_ty, named_key));
384-
} else {
385-
diag.delay_as_bug();
386-
}
387-
}
388-
389348
RegionErrorKind::BoundUniversalRegionError {
390349
longer_fr,
391350
placeholder,

compiler/rustc_borrowck/src/handle_placeholders.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ use tracing::debug;
1515
use crate::constraints::{ConstraintSccIndex, OutlivesConstraintSet};
1616
use crate::consumers::OutlivesConstraint;
1717
use crate::diagnostics::UniverseInfo;
18-
use crate::member_constraints::MemberConstraintSet;
1918
use crate::region_infer::values::{LivenessValues, PlaceholderIndices};
2019
use crate::region_infer::{ConstraintSccs, RegionDefinition, Representative, TypeTest};
2120
use crate::ty::VarianceDiagInfo;
@@ -30,7 +29,6 @@ pub(crate) struct LoweredConstraints<'tcx> {
3029
pub(crate) constraint_sccs: Sccs<RegionVid, ConstraintSccIndex>,
3130
pub(crate) definitions: Frozen<IndexVec<RegionVid, RegionDefinition<'tcx>>>,
3231
pub(crate) scc_annotations: IndexVec<ConstraintSccIndex, RegionTracker>,
33-
pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>,
3432
pub(crate) outlives_constraints: Frozen<OutlivesConstraintSet<'tcx>>,
3533
pub(crate) type_tests: Vec<TypeTest<'tcx>>,
3634
pub(crate) liveness_constraints: LivenessValues,
@@ -143,9 +141,10 @@ impl scc::Annotation for RegionTracker {
143141

144142
/// Determines if the region variable definitions contain
145143
/// placeholders, and compute them for later use.
146-
fn region_definitions<'tcx>(
147-
universal_regions: &UniversalRegions<'tcx>,
144+
// FIXME: This is also used by opaque type handling. Move it to a separate file.
145+
pub(super) fn region_definitions<'tcx>(
148146
infcx: &BorrowckInferCtxt<'tcx>,
147+
universal_regions: &UniversalRegions<'tcx>,
149148
) -> (Frozen<IndexVec<RegionVid, RegionDefinition<'tcx>>>, bool) {
150149
let var_infos = infcx.get_region_var_infos();
151150
// Create a RegionDefinition for each inference variable. This happens here because
@@ -209,14 +208,13 @@ pub(crate) fn compute_sccs_applying_placeholder_outlives_constraints<'tcx>(
209208
infcx: &BorrowckInferCtxt<'tcx>,
210209
) -> LoweredConstraints<'tcx> {
211210
let universal_regions = &universal_region_relations.universal_regions;
212-
let (definitions, has_placeholders) = region_definitions(universal_regions, infcx);
211+
let (definitions, has_placeholders) = region_definitions(infcx, universal_regions);
213212

214213
let MirTypeckRegionConstraints {
215214
placeholder_indices,
216215
placeholder_index_to_region: _,
217216
liveness_constraints,
218217
mut outlives_constraints,
219-
member_constraints,
220218
universe_causes,
221219
type_tests,
222220
} = constraints;
@@ -242,7 +240,6 @@ pub(crate) fn compute_sccs_applying_placeholder_outlives_constraints<'tcx>(
242240

243241
return LoweredConstraints {
244242
type_tests,
245-
member_constraints,
246243
constraint_sccs,
247244
scc_annotations: scc_annotations.scc_to_annotation,
248245
definitions,
@@ -279,7 +276,6 @@ pub(crate) fn compute_sccs_applying_placeholder_outlives_constraints<'tcx>(
279276
constraint_sccs,
280277
definitions,
281278
scc_annotations,
282-
member_constraints,
283279
outlives_constraints: Frozen::freeze(outlives_constraints),
284280
type_tests,
285281
liveness_constraints,

compiler/rustc_borrowck/src/lib.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ mod dataflow;
7878
mod def_use;
7979
mod diagnostics;
8080
mod handle_placeholders;
81-
mod member_constraints;
8281
mod nll;
8382
mod path_utils;
8483
mod place_ext;
@@ -335,9 +334,10 @@ fn do_mir_borrowck<'tcx>(
335334

336335
// Run the MIR type-checker.
337336
let MirTypeckResults {
338-
constraints,
337+
mut constraints,
339338
universal_region_relations,
340-
opaque_type_values,
339+
region_bound_pairs,
340+
known_type_outlives_obligations,
341341
polonius_context,
342342
} = type_check::type_check(
343343
root_cx,
@@ -352,6 +352,17 @@ fn do_mir_borrowck<'tcx>(
352352
Rc::clone(&location_map),
353353
);
354354

355+
let opaque_type_errors = region_infer::opaque_types::handle_opaque_type_uses(
356+
root_cx,
357+
&infcx,
358+
&body,
359+
&universal_region_relations,
360+
&region_bound_pairs,
361+
&known_type_outlives_obligations,
362+
&location_map,
363+
&mut constraints,
364+
);
365+
355366
// Compute non-lexical lifetimes using the constraints computed
356367
// by typechecking the MIR body.
357368
let nll::NllOutput {
@@ -375,8 +386,6 @@ fn do_mir_borrowck<'tcx>(
375386
polonius_context,
376387
);
377388

378-
let opaque_type_errors = regioncx.infer_opaque_types(root_cx, &infcx, opaque_type_values);
379-
380389
// Dump MIR results into a file, if that is enabled. This lets us
381390
// write unit-tests, as well as helping with debugging.
382391
nll::dump_nll_mir(&infcx, body, &regioncx, &opt_closure_req, &borrow_set);

0 commit comments

Comments
 (0)