Skip to content

Commit f736683

Browse files
committed
waddup gamers!
1 parent 269d5b5 commit f736683

28 files changed

+676
-463
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: 84 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,31 @@ 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+
308+
/// Start borrow checking by collecting the region constraints for
309+
/// the current body. This initializes the relevant data structures
310+
/// and then type checks the MIR body.
311+
fn borrowck_collect_region_constraints<'tcx>(
299312
root_cx: &mut BorrowCheckRootCtxt<'tcx>,
300313
def: LocalDefId,
301-
) -> PropagatedBorrowCheckResults<'tcx> {
314+
) -> CollectRegionConstraintsResult<'tcx> {
302315
let tcx = root_cx.tcx;
303316
let infcx = BorrowckInferCtxt::new(tcx, def, root_cx.root_def_id());
304317
let (input_body, promoted) = tcx.mir_promoted(def);
@@ -334,10 +347,11 @@ fn do_mir_borrowck<'tcx>(
334347

335348
// Run the MIR type-checker.
336349
let MirTypeckResults {
337-
mut constraints,
350+
constraints,
338351
universal_region_relations,
339352
region_bound_pairs,
340353
known_type_outlives_obligations,
354+
deferred_closure_requirements,
341355
polonius_context,
342356
} = type_check::type_check(
343357
root_cx,
@@ -352,16 +366,53 @@ fn do_mir_borrowck<'tcx>(
352366
Rc::clone(&location_map),
353367
);
354368

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

366417
// Compute non-lexical lifetimes using the constraints computed
367418
// by typechecking the MIR body.
@@ -481,7 +532,7 @@ fn do_mir_borrowck<'tcx>(
481532

482533
// Compute and report region errors, if any.
483534
if nll_errors.is_empty() {
484-
mbcx.report_opaque_type_errors(opaque_type_errors);
535+
mbcx.report_opaque_type_errors(deferred_opaque_type_errors);
485536
} else {
486537
mbcx.report_region_errors(nll_errors);
487538
}

compiler/rustc_borrowck/src/nll.rs

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

76+
/// Computes the closure requirements given the current inference state.
77+
///
78+
/// This is intended to be used by before [BorrowCheckRootCtxt::handle_opaque_type_uses]
79+
/// because applying member constraints may rely on closure requirements.
80+
/// This is frequently the case of async functions where pretty much everything
81+
/// happens inside of the inner async block but the opaque only gets constrained
82+
/// in the parent function.
83+
pub(crate) fn compute_closure_requirements_modulo_opaques<'tcx>(
84+
infcx: &BorrowckInferCtxt<'tcx>,
85+
body: &Body<'tcx>,
86+
location_map: Rc<DenseLocationMap>,
87+
universal_region_relations: &Frozen<UniversalRegionRelations<'tcx>>,
88+
constraints: &MirTypeckRegionConstraints<'tcx>,
89+
) -> Option<ClosureRegionRequirements<'tcx>> {
90+
// FIXME(closure-req-clone): we shouldn't have to clone all this stuff here.
91+
// Computing the region graph should take at least some of it by reference/`Rc`.
92+
let lowered_constraints = compute_sccs_applying_placeholder_outlives_constraints(
93+
constraints.clone(),
94+
&universal_region_relations,
95+
infcx,
96+
);
97+
let mut regioncx = RegionInferenceContext::new(
98+
&infcx,
99+
lowered_constraints,
100+
universal_region_relations.clone(),
101+
location_map.clone(),
102+
);
103+
104+
let (closure_region_requirements, _nll_errors) = regioncx.solve(infcx, body, None);
105+
closure_region_requirements
106+
}
107+
76108
/// Computes the (non-lexical) regions from the input MIR.
77109
///
78110
/// This may result in errors being reported.

0 commit comments

Comments
 (0)