Skip to content

Commit 99a2d1a

Browse files
committed
support revealing-uses in closures
1 parent abf6e65 commit 99a2d1a

File tree

11 files changed

+374
-110
lines changed

11 files changed

+374
-110
lines changed

compiler/rustc_borrowck/src/consumers.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub use super::polonius::legacy::{
1515
RichLocation, RustcFacts,
1616
};
1717
pub use super::region_infer::RegionInferenceContext;
18-
use crate::{BorrowCheckRootCtxt, do_mir_borrowck};
18+
use crate::BorrowCheckRootCtxt;
1919

2020
/// Options determining the output behavior of [`get_body_with_borrowck_facts`].
2121
///
@@ -101,6 +101,6 @@ pub fn get_body_with_borrowck_facts(
101101
def_id: LocalDefId,
102102
options: ConsumerOptions,
103103
) -> BodyWithBorrowckFacts<'_> {
104-
let mut root_cx = BorrowCheckRootCtxt::new(tcx, def_id);
105-
*do_mir_borrowck(&mut root_cx, def_id, Some(options)).1.unwrap()
104+
let root_cx = BorrowCheckRootCtxt::new(tcx, def_id);
105+
*root_cx.borrowck_root(Some(options)).1.unwrap()
106106
}

compiler/rustc_borrowck/src/lib.rs

+116-14
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,15 @@ use std::borrow::Cow;
2121
use std::cell::RefCell;
2222
use std::marker::PhantomData;
2323
use std::ops::{ControlFlow, Deref};
24+
use std::rc::Rc;
2425

2526
use borrow_set::LocalsStateAtExit;
2627
use diagnostics::RegionErrors;
28+
use polonius_engine::AllFacts;
29+
use region_infer::opaque_types::DeferredOpaqueTypeError;
2730
use root_cx::BorrowCheckRootCtxt;
2831
use rustc_abi::FieldIdx;
32+
use rustc_data_structures::frozen::Frozen;
2933
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
3034
use rustc_data_structures::graph::dominators::Dominators;
3135
use rustc_errors::LintDiagnostic;
@@ -34,6 +38,7 @@ use rustc_hir::CRATE_HIR_ID;
3438
use rustc_hir::def_id::LocalDefId;
3539
use rustc_index::bit_set::{DenseBitSet, MixedBitSet};
3640
use rustc_index::{IndexSlice, IndexVec};
41+
use rustc_infer::infer::outlives::env::RegionBoundPairs;
3742
use rustc_infer::infer::{
3843
InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
3944
};
@@ -49,23 +54,28 @@ use rustc_mir_dataflow::impls::{
4954
use rustc_mir_dataflow::move_paths::{
5055
InitIndex, InitLocation, LookupResult, MoveData, MovePathIndex,
5156
};
57+
use rustc_mir_dataflow::points::DenseLocationMap;
5258
use rustc_mir_dataflow::{Analysis, EntryStates, Results, ResultsVisitor, visit_results};
5359
use rustc_session::lint::builtin::{TAIL_EXPR_DROP_ORDER, UNUSED_MUT};
5460
use rustc_span::{ErrorGuaranteed, Span, Symbol};
5561
use smallvec::SmallVec;
5662
use tracing::{debug, instrument};
63+
use type_check::free_region_relations::UniversalRegionRelations;
64+
use type_check::{Locations, MirTypeckRegionConstraints, MirTypeckResults};
5765

5866
use crate::borrow_set::{BorrowData, BorrowSet};
59-
use crate::consumers::{BodyWithBorrowckFacts, ConsumerOptions};
67+
use crate::consumers::{BodyWithBorrowckFacts, ConsumerOptions, RustcFacts};
6068
use crate::dataflow::{BorrowIndex, Borrowck, BorrowckDomain, Borrows};
6169
use crate::diagnostics::{
6270
AccessKind, BorrowckDiagnosticsBuffer, IllegalMoveOriginKind, MoveError, RegionName,
6371
};
6472
use crate::path_utils::*;
6573
use crate::place_ext::PlaceExt;
6674
use crate::places_conflict::{PlaceConflictBias, places_conflict};
67-
use crate::polonius::PoloniusDiagnosticsContext;
68-
use crate::polonius::legacy::{PoloniusLocationTable, PoloniusOutput};
75+
use crate::polonius::legacy::{
76+
PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput,
77+
};
78+
use crate::polonius::{PoloniusContext, PoloniusDiagnosticsContext};
6979
use crate::prefixes::PrefixSet;
7080
use crate::region_infer::RegionInferenceContext;
7181
use crate::renumber::RegionCtxt;
@@ -127,12 +137,8 @@ fn mir_borrowck(
127137
let opaque_types = ConcreteOpaqueTypes(Default::default());
128138
Ok(tcx.arena.alloc(opaque_types))
129139
} else {
130-
let mut root_cx = BorrowCheckRootCtxt::new(tcx, def);
131-
let PropagatedBorrowCheckResults { closure_requirements, used_mut_upvars } =
132-
do_mir_borrowck(&mut root_cx, def, None).0;
133-
debug_assert!(closure_requirements.is_none());
134-
debug_assert!(used_mut_upvars.is_empty());
135-
root_cx.finalize()
140+
let root_cx = BorrowCheckRootCtxt::new(tcx, def);
141+
root_cx.borrowck_root(None).0
136142
}
137143
}
138144

@@ -144,6 +150,8 @@ struct PropagatedBorrowCheckResults<'tcx> {
144150
used_mut_upvars: SmallVec<[FieldIdx; 8]>,
145151
}
146152

153+
type DeferredClosureRequirements<'tcx> = Vec<(LocalDefId, ty::GenericArgsRef<'tcx>, Locations)>;
154+
147155
/// After we borrow check a closure, we are left with various
148156
/// requirements that we have inferred between the free regions that
149157
/// appear in the closure's signature or on its field types. These
@@ -282,6 +290,24 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
282290
}
283291
}
284292

293+
struct BorrowckState<'tcx> {
294+
infcx: BorrowckInferCtxt<'tcx>,
295+
body_owned: Body<'tcx>,
296+
promoted: IndexVec<Promoted, Body<'tcx>>,
297+
move_data: MoveData<'tcx>,
298+
borrow_set: BorrowSet<'tcx>,
299+
location_table: PoloniusLocationTable,
300+
location_map: Rc<DenseLocationMap>,
301+
universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
302+
region_bound_pairs: Frozen<RegionBoundPairs<'tcx>>,
303+
known_type_outlives_obligations: Frozen<Vec<ty::PolyTypeOutlivesPredicate<'tcx>>>,
304+
constraints: MirTypeckRegionConstraints<'tcx>,
305+
deferred_closure_requirements: DeferredClosureRequirements<'tcx>,
306+
deferred_opaque_type_errors: Vec<DeferredOpaqueTypeError<'tcx>>,
307+
polonius_facts: Option<AllFacts<RustcFacts>>,
308+
polonius_context: Option<PoloniusContext>,
309+
}
310+
285311
/// Perform the actual borrow checking.
286312
///
287313
/// Use `consumer_options: None` for the default behavior of returning
@@ -290,11 +316,11 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
290316
///
291317
/// For nested bodies this should only be called through `root_cx.get_or_insert_nested`.
292318
#[instrument(skip(root_cx), level = "debug")]
293-
fn do_mir_borrowck<'tcx>(
319+
fn start_do_mir_borrowck<'tcx>(
294320
root_cx: &mut BorrowCheckRootCtxt<'tcx>,
295321
def: LocalDefId,
296322
consumer_options: Option<ConsumerOptions>,
297-
) -> (PropagatedBorrowCheckResults<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
323+
) -> BorrowckState<'tcx> {
298324
let tcx = root_cx.tcx;
299325
let infcx = BorrowckInferCtxt::new(tcx, def);
300326
let (input_body, promoted) = tcx.mir_promoted(def);
@@ -315,6 +341,7 @@ fn do_mir_borrowck<'tcx>(
315341
let body = &body_owned; // no further changes
316342

317343
let location_table = PoloniusLocationTable::new(body);
344+
let location_map = Rc::new(DenseLocationMap::new(body));
318345

319346
let move_data = MoveData::gather_moves(body, tcx, |_| true);
320347

@@ -325,6 +352,78 @@ fn do_mir_borrowck<'tcx>(
325352
let locals_are_invalidated_at_exit = tcx.hir_body_owner_kind(def).is_fn_or_closure();
326353
let borrow_set = BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &move_data);
327354

355+
let is_polonius_legacy_enabled = infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled();
356+
let polonius_input = consumer_options.map(|c| c.polonius_input()).unwrap_or_default()
357+
|| is_polonius_legacy_enabled;
358+
let mut polonius_facts =
359+
(polonius_input || PoloniusFacts::enabled(infcx.tcx)).then_some(PoloniusFacts::default());
360+
361+
// Run the MIR type-checker.
362+
let MirTypeckResults {
363+
constraints,
364+
universal_region_relations,
365+
region_bound_pairs,
366+
known_type_outlives_obligations,
367+
deferred_closure_requirements,
368+
polonius_context,
369+
} = type_check::type_check(
370+
root_cx,
371+
&infcx,
372+
&body,
373+
&promoted,
374+
universal_regions,
375+
&location_table,
376+
&borrow_set,
377+
&mut polonius_facts,
378+
flow_inits,
379+
&move_data,
380+
Rc::clone(&location_map),
381+
);
382+
383+
BorrowckState {
384+
infcx,
385+
body_owned,
386+
promoted,
387+
move_data,
388+
borrow_set,
389+
location_table,
390+
location_map,
391+
universal_region_relations,
392+
region_bound_pairs,
393+
known_type_outlives_obligations,
394+
constraints,
395+
deferred_closure_requirements,
396+
deferred_opaque_type_errors: Default::default(),
397+
polonius_facts,
398+
polonius_context,
399+
}
400+
}
401+
402+
fn resume_do_mir_borrowck<'tcx>(
403+
root_cx: &mut BorrowCheckRootCtxt<'tcx>,
404+
consumer_options: Option<ConsumerOptions>,
405+
BorrowckState {
406+
infcx,
407+
body_owned,
408+
promoted,
409+
move_data,
410+
borrow_set,
411+
location_table,
412+
location_map,
413+
universal_region_relations,
414+
region_bound_pairs: _,
415+
known_type_outlives_obligations: _,
416+
constraints,
417+
deferred_closure_requirements,
418+
deferred_opaque_type_errors,
419+
polonius_facts,
420+
polonius_context,
421+
}: BorrowckState<'tcx>,
422+
) -> (PropagatedBorrowCheckResults<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
423+
assert!(!infcx.has_opaque_types_in_storage());
424+
assert!(deferred_closure_requirements.is_empty());
425+
let body = &body_owned;
426+
328427
// Compute non-lexical lifetimes.
329428
let nll::NllOutput {
330429
regioncx,
@@ -336,14 +435,17 @@ fn do_mir_borrowck<'tcx>(
336435
} = nll::compute_regions(
337436
root_cx,
338437
&infcx,
339-
universal_regions,
340438
body,
341-
&promoted,
342439
&location_table,
343-
flow_inits,
344440
&move_data,
345441
&borrow_set,
442+
location_map,
346443
consumer_options,
444+
universal_region_relations,
445+
constraints,
446+
deferred_opaque_type_errors,
447+
polonius_facts,
448+
polonius_context,
347449
);
348450

349451
// Dump MIR results into a file, if that is enabled. This lets us

compiler/rustc_borrowck/src/nll.rs

+39-45
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,34 @@ use std::path::PathBuf;
55
use std::rc::Rc;
66
use std::str::FromStr;
77

8-
use polonius_engine::{Algorithm, Output};
8+
use polonius_engine::{Algorithm, AllFacts, Output};
9+
use rustc_data_structures::frozen::Frozen;
910
use rustc_index::IndexSlice;
1011
use rustc_middle::mir::pretty::{PrettyPrintMirOptions, dump_mir_with_options};
1112
use rustc_middle::mir::{Body, PassWhere, Promoted, create_dump_file, dump_enabled, dump_mir};
1213
use rustc_middle::ty::print::with_no_trimmed_paths;
1314
use rustc_middle::ty::{self, TyCtxt};
14-
use rustc_mir_dataflow::ResultsCursor;
15-
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
1615
use rustc_mir_dataflow::move_paths::MoveData;
1716
use rustc_mir_dataflow::points::DenseLocationMap;
1817
use rustc_session::config::MirIncludeSpans;
1918
use rustc_span::sym;
2019
use tracing::{debug, instrument};
2120

2221
use crate::borrow_set::BorrowSet;
23-
use crate::consumers::ConsumerOptions;
22+
use crate::consumers::{ConsumerOptions, RustcFacts};
2423
use crate::diagnostics::RegionErrors;
25-
use crate::polonius::PoloniusDiagnosticsContext;
2624
use crate::polonius::legacy::{
2725
PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput,
2826
};
27+
use crate::polonius::{PoloniusContext, PoloniusDiagnosticsContext};
2928
use crate::region_infer::RegionInferenceContext;
30-
use crate::region_infer::opaque_types::handle_opaque_type_uses;
31-
use crate::type_check::{self, MirTypeckResults};
29+
use crate::region_infer::opaque_types::DeferredOpaqueTypeError;
30+
use crate::type_check::MirTypeckRegionConstraints;
31+
use crate::type_check::free_region_relations::UniversalRegionRelations;
3232
use crate::universal_regions::UniversalRegions;
3333
use crate::{
34-
BorrowCheckRootCtxt, BorrowckInferCtxt, ClosureOutlivesSubject, ClosureRegionRequirements,
35-
polonius, renumber,
34+
BorrowCheckRootCtxt, BorrowckInferCtxt, BorrowckState, ClosureOutlivesSubject,
35+
ClosureRegionRequirements, polonius, renumber,
3636
};
3737

3838
/// The output of `nll::compute_regions`. This includes the computed `RegionInferenceContext`, any
@@ -73,55 +73,49 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
7373
universal_regions
7474
}
7575

76-
/// Computes the (non-lexical) regions from the input MIR.
76+
pub(crate) fn compute_closure_requirements_modulo_opaques<'tcx>(
77+
partial_result: &BorrowckState<'tcx>,
78+
) -> Option<ClosureRegionRequirements<'tcx>> {
79+
let BorrowckState {
80+
infcx,
81+
body_owned,
82+
location_map,
83+
universal_region_relations,
84+
constraints,
85+
..
86+
} = partial_result;
87+
88+
let mut regioncx = RegionInferenceContext::new(
89+
&infcx,
90+
constraints.clone(),
91+
universal_region_relations.clone(),
92+
location_map.clone(),
93+
);
94+
let (closure_region_requirements, _nll_errors) = regioncx.solve(infcx, &body_owned, None);
95+
closure_region_requirements
96+
}
97+
98+
/// Computes and checks the region graph for the given constraints.
7799
///
78100
/// This may result in errors being reported.
79-
pub(crate) fn compute_regions<'a, 'tcx>(
101+
pub(crate) fn compute_regions<'tcx>(
80102
root_cx: &mut BorrowCheckRootCtxt<'tcx>,
81103
infcx: &BorrowckInferCtxt<'tcx>,
82-
universal_regions: UniversalRegions<'tcx>,
83104
body: &Body<'tcx>,
84-
promoted: &IndexSlice<Promoted, Body<'tcx>>,
85105
location_table: &PoloniusLocationTable,
86-
flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
87106
move_data: &MoveData<'tcx>,
88107
borrow_set: &BorrowSet<'tcx>,
108+
location_map: Rc<DenseLocationMap>,
89109
consumer_options: Option<ConsumerOptions>,
110+
universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
111+
constraints: MirTypeckRegionConstraints<'tcx>,
112+
deferred_opaque_type_errors: Vec<DeferredOpaqueTypeError<'tcx>>,
113+
mut polonius_facts: Option<AllFacts<RustcFacts>>,
114+
polonius_context: Option<PoloniusContext>,
90115
) -> NllOutput<'tcx> {
91116
let is_polonius_legacy_enabled = infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled();
92-
let polonius_input = consumer_options.map(|c| c.polonius_input()).unwrap_or_default()
93-
|| is_polonius_legacy_enabled;
94117
let polonius_output = consumer_options.map(|c| c.polonius_output()).unwrap_or_default()
95118
|| is_polonius_legacy_enabled;
96-
let mut polonius_facts =
97-
(polonius_input || PoloniusFacts::enabled(infcx.tcx)).then_some(PoloniusFacts::default());
98-
99-
let location_map = Rc::new(DenseLocationMap::new(body));
100-
101-
// Run the MIR type-checker.
102-
let MirTypeckResults { constraints, universal_region_relations, polonius_context } =
103-
type_check::type_check(
104-
root_cx,
105-
infcx,
106-
body,
107-
promoted,
108-
universal_regions,
109-
location_table,
110-
borrow_set,
111-
&mut polonius_facts,
112-
flow_inits,
113-
move_data,
114-
Rc::clone(&location_map),
115-
);
116-
117-
let (constraints, deferred_opaque_type_errors) = handle_opaque_type_uses(
118-
root_cx,
119-
infcx,
120-
constraints,
121-
&universal_region_relations,
122-
Rc::clone(&location_map),
123-
);
124-
125119
// If requested, emit legacy polonius facts.
126120
polonius::legacy::emit_facts(
127121
&mut polonius_facts,

0 commit comments

Comments
 (0)