Skip to content

Commit f55097d

Browse files
Auto merge of #145925 - lcnr:revealing-use-closures-2, r=<try>
support non-defining uses in closures
2 parents 4f808ba + 9a3facf commit f55097d

28 files changed

+686
-460
lines changed

compiler/rustc_borrowck/src/consumers.rs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub use super::polonius::legacy::{
1717
RichLocation, RustcFacts,
1818
};
1919
pub use super::region_infer::RegionInferenceContext;
20-
use crate::{BorrowCheckRootCtxt, do_mir_borrowck};
20+
use crate::BorrowCheckRootCtxt;
2121

2222
/// Struct used during mir borrowck to collect bodies with facts for a typeck root and all
2323
/// its nested bodies.
@@ -127,13 +127,6 @@ pub fn get_bodies_with_borrowck_facts(
127127
) -> FxHashMap<LocalDefId, BodyWithBorrowckFacts<'_>> {
128128
let mut root_cx =
129129
BorrowCheckRootCtxt::new(tcx, root_def_id, Some(BorrowckConsumer::new(options)));
130-
131-
// See comment in `rustc_borrowck::mir_borrowck`
132-
let nested_bodies = tcx.nested_bodies_within(root_def_id);
133-
for def_id in nested_bodies {
134-
root_cx.get_or_insert_nested(def_id);
135-
}
136-
137-
do_mir_borrowck(&mut root_cx, root_def_id);
130+
root_cx.do_mir_borrowck();
138131
root_cx.consumer.unwrap().bodies
139132
}

compiler/rustc_borrowck/src/lib.rs

Lines changed: 83 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ use std::ops::{ControlFlow, Deref};
2222
use std::rc::Rc;
2323

2424
use borrow_set::LocalsStateAtExit;
25+
use polonius_engine::AllFacts;
2526
use root_cx::BorrowCheckRootCtxt;
2627
use rustc_abi::FieldIdx;
28+
use rustc_data_structures::frozen::Frozen;
2729
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
2830
use rustc_data_structures::graph::dominators::Dominators;
2931
use rustc_errors::LintDiagnostic;
@@ -32,6 +34,7 @@ use rustc_hir::CRATE_HIR_ID;
3234
use rustc_hir::def_id::LocalDefId;
3335
use rustc_index::bit_set::MixedBitSet;
3436
use rustc_index::{IndexSlice, IndexVec};
37+
use rustc_infer::infer::outlives::env::RegionBoundPairs;
3538
use rustc_infer::infer::{
3639
InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
3740
};
@@ -53,23 +56,25 @@ use smallvec::SmallVec;
5356
use tracing::{debug, instrument};
5457

5558
use crate::borrow_set::{BorrowData, BorrowSet};
56-
use crate::consumers::BodyWithBorrowckFacts;
59+
use crate::consumers::{BodyWithBorrowckFacts, RustcFacts};
5760
use crate::dataflow::{BorrowIndex, Borrowck, BorrowckDomain, Borrows};
5861
use crate::diagnostics::{
5962
AccessKind, BorrowckDiagnosticsBuffer, IllegalMoveOriginKind, MoveError, RegionName,
6063
};
6164
use crate::path_utils::*;
6265
use crate::place_ext::PlaceExt;
6366
use crate::places_conflict::{PlaceConflictBias, places_conflict};
64-
use crate::polonius::PoloniusDiagnosticsContext;
6567
use crate::polonius::legacy::{
6668
PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput,
6769
};
70+
use crate::polonius::{PoloniusContext, PoloniusDiagnosticsContext};
6871
use crate::prefixes::PrefixSet;
6972
use crate::region_infer::RegionInferenceContext;
73+
use crate::region_infer::opaque_types::DeferredOpaqueTypeError;
7074
use crate::renumber::RegionCtxt;
7175
use crate::session_diagnostics::VarNeedNotMut;
72-
use crate::type_check::MirTypeckResults;
76+
use crate::type_check::free_region_relations::UniversalRegionRelations;
77+
use crate::type_check::{Locations, MirTypeckRegionConstraints, MirTypeckResults};
7378

7479
mod borrow_set;
7580
mod borrowck_errors;
@@ -129,18 +134,7 @@ fn mir_borrowck(
129134
Ok(tcx.arena.alloc(opaque_types))
130135
} else {
131136
let mut root_cx = BorrowCheckRootCtxt::new(tcx, def, None);
132-
// We need to manually borrowck all nested bodies from the HIR as
133-
// we do not generate MIR for dead code. Not doing so causes us to
134-
// never check closures in dead code.
135-
let nested_bodies = tcx.nested_bodies_within(def);
136-
for def_id in nested_bodies {
137-
root_cx.get_or_insert_nested(def_id);
138-
}
139-
140-
let PropagatedBorrowCheckResults { closure_requirements, used_mut_upvars } =
141-
do_mir_borrowck(&mut root_cx, def);
142-
debug_assert!(closure_requirements.is_none());
143-
debug_assert!(used_mut_upvars.is_empty());
137+
root_cx.do_mir_borrowck();
144138
root_cx.finalize()
145139
}
146140
}
@@ -153,6 +147,8 @@ struct PropagatedBorrowCheckResults<'tcx> {
153147
used_mut_upvars: SmallVec<[FieldIdx; 8]>,
154148
}
155149

150+
type DeferredClosureRequirements<'tcx> = Vec<(LocalDefId, ty::GenericArgsRef<'tcx>, Locations)>;
151+
156152
/// After we borrow check a closure, we are left with various
157153
/// requirements that we have inferred between the free regions that
158154
/// appear in the closure's signature or on its field types. These
@@ -291,14 +287,30 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
291287
}
292288
}
293289

294-
/// Perform the actual borrow checking.
295-
///
296-
/// For nested bodies this should only be called through `root_cx.get_or_insert_nested`.
297-
#[instrument(skip(root_cx), level = "debug")]
298-
fn do_mir_borrowck<'tcx>(
290+
struct CollectRegionConstraintsResult<'tcx> {
291+
infcx: BorrowckInferCtxt<'tcx>,
292+
body_owned: Body<'tcx>,
293+
promoted: IndexVec<Promoted, Body<'tcx>>,
294+
move_data: MoveData<'tcx>,
295+
borrow_set: BorrowSet<'tcx>,
296+
location_table: PoloniusLocationTable,
297+
location_map: Rc<DenseLocationMap>,
298+
universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
299+
region_bound_pairs: Frozen<RegionBoundPairs<'tcx>>,
300+
known_type_outlives_obligations: Frozen<Vec<ty::PolyTypeOutlivesPredicate<'tcx>>>,
301+
constraints: MirTypeckRegionConstraints<'tcx>,
302+
deferred_closure_requirements: DeferredClosureRequirements<'tcx>,
303+
deferred_opaque_type_errors: Vec<DeferredOpaqueTypeError<'tcx>>,
304+
polonius_facts: Option<AllFacts<RustcFacts>>,
305+
polonius_context: Option<PoloniusContext>,
306+
}
307+
/// Start borrow checking by collecting the region constraints for
308+
/// the current body. This initializes the relevant data structures
309+
/// and then type checks the MIR body.
310+
fn borrowck_collect_region_constraints<'tcx>(
299311
root_cx: &mut BorrowCheckRootCtxt<'tcx>,
300312
def: LocalDefId,
301-
) -> PropagatedBorrowCheckResults<'tcx> {
313+
) -> CollectRegionConstraintsResult<'tcx> {
302314
let tcx = root_cx.tcx;
303315
let infcx = BorrowckInferCtxt::new(tcx, def, root_cx.root_def_id());
304316
let (input_body, promoted) = tcx.mir_promoted(def);
@@ -334,10 +346,11 @@ fn do_mir_borrowck<'tcx>(
334346

335347
// Run the MIR type-checker.
336348
let MirTypeckResults {
337-
mut constraints,
349+
constraints,
338350
universal_region_relations,
339351
region_bound_pairs,
340352
known_type_outlives_obligations,
353+
deferred_closure_requirements,
341354
polonius_context,
342355
} = type_check::type_check(
343356
root_cx,
@@ -352,16 +365,53 @@ fn do_mir_borrowck<'tcx>(
352365
Rc::clone(&location_map),
353366
);
354367

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-
);
368+
CollectRegionConstraintsResult {
369+
infcx,
370+
body_owned,
371+
promoted,
372+
move_data,
373+
borrow_set,
374+
location_table,
375+
location_map,
376+
universal_region_relations,
377+
region_bound_pairs,
378+
known_type_outlives_obligations,
379+
constraints,
380+
deferred_closure_requirements,
381+
deferred_opaque_type_errors: Default::default(),
382+
polonius_facts,
383+
polonius_context,
384+
}
385+
}
386+
387+
/// Using the region constraints computed by [borrowck_collect_region_constraints]
388+
/// and the additional constraints from [handle_opaque_type_uses] TODO, compute
389+
/// the region graph and actually check for any borrowck errors.
390+
fn borrowck_check_region_constraints<'tcx>(
391+
root_cx: &mut BorrowCheckRootCtxt<'tcx>,
392+
CollectRegionConstraintsResult {
393+
infcx,
394+
body_owned,
395+
promoted,
396+
move_data,
397+
borrow_set,
398+
location_table,
399+
location_map,
400+
universal_region_relations,
401+
region_bound_pairs: _,
402+
known_type_outlives_obligations: _,
403+
constraints,
404+
deferred_closure_requirements,
405+
deferred_opaque_type_errors,
406+
polonius_facts,
407+
polonius_context,
408+
}: CollectRegionConstraintsResult<'tcx>,
409+
) -> PropagatedBorrowCheckResults<'tcx> {
410+
assert!(!infcx.has_opaque_types_in_storage());
411+
assert!(deferred_closure_requirements.is_empty());
412+
let tcx = root_cx.tcx;
413+
let body = &body_owned;
414+
let def = body.source.def_id().expect_local();
365415

366416
// Compute non-lexical lifetimes using the constraints computed
367417
// by typechecking the MIR body.
@@ -481,7 +531,7 @@ fn do_mir_borrowck<'tcx>(
481531

482532
// Compute and report region errors, if any.
483533
if nll_errors.is_empty() {
484-
mbcx.report_opaque_type_errors(opaque_type_errors);
534+
mbcx.report_opaque_type_errors(deferred_opaque_type_errors);
485535
} else {
486536
mbcx.report_region_errors(nll_errors);
487537
}

compiler/rustc_borrowck/src/nll.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,29 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
7373
universal_regions
7474
}
7575

76+
pub(crate) fn compute_closure_requirements_modulo_opaques<'tcx>(
77+
infcx: &BorrowckInferCtxt<'tcx>,
78+
body: &Body<'tcx>,
79+
location_map: Rc<DenseLocationMap>,
80+
universal_region_relations: &Frozen<UniversalRegionRelations<'tcx>>,
81+
constraints: &MirTypeckRegionConstraints<'tcx>,
82+
) -> Option<ClosureRegionRequirements<'tcx>> {
83+
let lowered_constraints = compute_sccs_applying_placeholder_outlives_constraints(
84+
constraints.clone(),
85+
&universal_region_relations,
86+
infcx,
87+
);
88+
let mut regioncx = RegionInferenceContext::new(
89+
&infcx,
90+
lowered_constraints,
91+
universal_region_relations.clone(),
92+
location_map.clone(),
93+
);
94+
95+
let (closure_region_requirements, _nll_errors) = regioncx.solve(infcx, body, None);
96+
closure_region_requirements
97+
}
98+
7699
/// Computes the (non-lexical) regions from the input MIR.
77100
///
78101
/// This may result in errors being reported.

0 commit comments

Comments
 (0)