Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b8160e9

Browse files
committed
use defining uses of all bodies to constrain non-defining uses
support non-defining uses in closures
1 parent a3993c5 commit b8160e9

File tree

17 files changed

+518
-232
lines changed

17 files changed

+518
-232
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-
mutconstraints,
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(#146079): 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,
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)

AltStyle によって変換されたページ (->オリジナル) /