Skip to content

Commit f83cf4b

Browse files
committed
add yield point to mir borrowck
1 parent 116e0e6 commit f83cf4b

File tree

12 files changed

+461
-130
lines changed

12 files changed

+461
-130
lines changed

compiler/rustc_borrowck/src/consumers.rs

+2-2
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
///
@@ -102,5 +102,5 @@ pub fn get_body_with_borrowck_facts(
102102
options: ConsumerOptions,
103103
) -> BodyWithBorrowckFacts<'_> {
104104
let mut root_cx = BorrowCheckRootCtxt::new(tcx, def_id);
105-
*do_mir_borrowck(&mut root_cx, def_id, Some(options)).1.unwrap()
105+
*root_cx.borrowck_root(Some(options)).1.unwrap()
106106
}

compiler/rustc_borrowck/src/lib.rs

+97-42
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! This query borrow-checks the MIR to (further) ensure it is not broken.
22
33
// tidy-alphabetical-start
4-
#![allow(internal_features)]
4+
#![allow(internal_features, unused)]
55
#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
66
#![doc(rust_logo)]
77
#![feature(assert_matches)]
@@ -21,15 +21,18 @@ 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

26+
use nll::YieldComputeRegions;
27+
use region_infer::opaque_types::{DeferredOpaqueTypeError, handle_opaque_type_uses};
2528
use root_cx::BorrowCheckRootCtxt;
2629
use rustc_abi::FieldIdx;
2730
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
2831
use rustc_data_structures::graph::dominators::Dominators;
2932
use rustc_errors::LintDiagnostic;
3033
use rustc_hir as hir;
3134
use rustc_hir::CRATE_HIR_ID;
32-
use rustc_hir::def_id::LocalDefId;
35+
use rustc_hir::def_id::{DefId, LocalDefId};
3336
use rustc_index::bit_set::{DenseBitSet, MixedBitSet};
3437
use rustc_index::{IndexSlice, IndexVec};
3538
use rustc_infer::infer::{
@@ -52,6 +55,7 @@ use rustc_session::lint::builtin::{TAIL_EXPR_DROP_ORDER, UNUSED_MUT};
5255
use rustc_span::{ErrorGuaranteed, Span, Symbol};
5356
use smallvec::SmallVec;
5457
use tracing::{debug, instrument};
58+
use type_check::Locations;
5559

5660
use crate::borrow_set::{BorrowData, BorrowSet};
5761
use crate::consumers::{BodyWithBorrowckFacts, ConsumerOptions};
@@ -126,11 +130,7 @@ fn mir_borrowck(
126130
Ok(tcx.arena.alloc(opaque_types))
127131
} else {
128132
let mut root_cx = BorrowCheckRootCtxt::new(tcx, def);
129-
let PropagatedBorrowCheckResults { closure_requirements, used_mut_upvars } =
130-
do_mir_borrowck(&mut root_cx, def, None).0;
131-
debug_assert!(closure_requirements.is_none());
132-
debug_assert!(used_mut_upvars.is_empty());
133-
root_cx.finalize()
133+
root_cx.borrowck_root(None).0
134134
}
135135
}
136136

@@ -142,6 +142,8 @@ struct PropagatedBorrowCheckResults<'tcx> {
142142
used_mut_upvars: SmallVec<[FieldIdx; 8]>,
143143
}
144144

145+
type DeferredClosureRequirements<'tcx> = Vec<(LocalDefId, ty::GenericArgsRef<'tcx>, Locations)>;
146+
145147
/// After we borrow check a closure, we are left with various
146148
/// requirements that we have inferred between the free regions that
147149
/// appear in the closure's signature or on its field types. These
@@ -280,6 +282,17 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
280282
}
281283
}
282284

285+
struct YieldDoMirBorrowck<'tcx> {
286+
infcx: BorrowckInferCtxt<'tcx>,
287+
body_owned: Body<'tcx>,
288+
promoted: IndexVec<Promoted, Body<'tcx>>,
289+
move_data: MoveData<'tcx>,
290+
locals_are_invalidated_at_exit: bool,
291+
borrow_set: BorrowSet<'tcx>,
292+
location_table: PoloniusLocationTable,
293+
yield_compute_regions: YieldComputeRegions<'tcx>,
294+
}
295+
283296
/// Perform the actual borrow checking.
284297
///
285298
/// Use `consumer_options: None` for the default behavior of returning
@@ -288,11 +301,11 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
288301
///
289302
/// For nested bodies this should only be called through `root_cx.get_or_insert_nested`.
290303
#[instrument(skip(root_cx), level = "debug")]
291-
fn do_mir_borrowck<'tcx>(
304+
fn start_do_mir_borrowck<'tcx>(
292305
root_cx: &mut BorrowCheckRootCtxt<'tcx>,
293306
def: LocalDefId,
294307
consumer_options: Option<ConsumerOptions>,
295-
) -> (PropagatedBorrowCheckResults<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
308+
) -> YieldDoMirBorrowck<'tcx> {
296309
let tcx = root_cx.tcx;
297310
let infcx = BorrowckInferCtxt::new(tcx, def);
298311
let (input_body, promoted) = tcx.mir_promoted(def);
@@ -303,33 +316,13 @@ fn do_mir_borrowck<'tcx>(
303316
root_cx.set_tainted_by_errors(e);
304317
}
305318

306-
let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
307-
for var_debug_info in &input_body.var_debug_info {
308-
if let VarDebugInfoContents::Place(place) = var_debug_info.value {
309-
if let Some(local) = place.as_local() {
310-
if let Some(prev_name) = local_names[local]
311-
&& var_debug_info.name != prev_name
312-
{
313-
span_bug!(
314-
var_debug_info.source_info.span,
315-
"local {:?} has many names (`{}` vs `{}`)",
316-
local,
317-
prev_name,
318-
var_debug_info.name
319-
);
320-
}
321-
local_names[local] = Some(var_debug_info.name);
322-
}
323-
}
324-
}
325-
326319
// Replace all regions with fresh inference variables. This
327320
// requires first making our own copy of the MIR. This copy will
328321
// be modified (in place) to contain non-lexical lifetimes. It
329322
// will have a lifetime tied to the inference context.
330323
let mut body_owned = input_body.clone();
331324
let mut promoted = input_promoted.to_owned();
332-
let free_regions = nll::replace_regions_in_mir(&infcx, &mut body_owned, &mut promoted);
325+
let universal_regions = nll::replace_regions_in_mir(&infcx, &mut body_owned, &mut promoted);
333326
let body = &body_owned; // no further changes
334327

335328
let location_table = PoloniusLocationTable::new(body);
@@ -343,6 +336,50 @@ fn do_mir_borrowck<'tcx>(
343336
let locals_are_invalidated_at_exit = tcx.hir_body_owner_kind(def).is_fn_or_closure();
344337
let borrow_set = BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &move_data);
345338

339+
let yield_compute_regions = nll::compute_regions(
340+
root_cx,
341+
&infcx,
342+
universal_regions,
343+
body,
344+
&promoted,
345+
&location_table,
346+
flow_inits,
347+
&move_data,
348+
&borrow_set,
349+
consumer_options,
350+
);
351+
352+
YieldDoMirBorrowck {
353+
infcx,
354+
body_owned,
355+
promoted,
356+
move_data,
357+
locals_are_invalidated_at_exit,
358+
borrow_set,
359+
location_table,
360+
yield_compute_regions,
361+
}
362+
}
363+
364+
fn resume_do_mir_borrowck<'tcx>(
365+
root_cx: &mut BorrowCheckRootCtxt<'tcx>,
366+
def: LocalDefId,
367+
consumer_options: Option<ConsumerOptions>,
368+
YieldDoMirBorrowck {
369+
infcx,
370+
body_owned,
371+
promoted,
372+
move_data,
373+
locals_are_invalidated_at_exit,
374+
borrow_set,
375+
location_table,
376+
yield_compute_regions,
377+
}: YieldDoMirBorrowck<'tcx>,
378+
) -> (PropagatedBorrowCheckResults<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
379+
assert!(!infcx.has_opaque_types_in_storage());
380+
let tcx = infcx.tcx;
381+
let body = &body_owned;
382+
346383
// Compute non-lexical lifetimes.
347384
let nll::NllOutput {
348385
regioncx,
@@ -351,17 +388,15 @@ fn do_mir_borrowck<'tcx>(
351388
opt_closure_req,
352389
nll_errors,
353390
polonius_diagnostics,
354-
} = nll::compute_regions(
391+
} = nll::resume_compute_regions(
355392
root_cx,
356393
&infcx,
357-
free_regions,
358394
body,
359-
&promoted,
360395
&location_table,
361-
flow_inits,
362396
&move_data,
363397
&borrow_set,
364398
consumer_options,
399+
yield_compute_regions,
365400
);
366401

367402
// Dump MIR results into a file, if that is enabled. This lets us
@@ -376,14 +411,14 @@ fn do_mir_borrowck<'tcx>(
376411
let movable_coroutine =
377412
// The first argument is the coroutine type passed by value
378413
if let Some(local) = body.local_decls.raw.get(1)
379-
// Get the interior types and args which typeck computed
380-
&& let ty::Coroutine(def_id, _) = *local.ty.kind()
381-
&& tcx.coroutine_movability(def_id) == hir::Movability::Movable
382-
{
383-
true
384-
} else {
385-
false
386-
};
414+
// Get the interior types and args which typeck computed
415+
&& let ty::Coroutine(def_id, _) = *local.ty.kind()
416+
&& tcx.coroutine_movability(def_id) == hir::Movability::Movable
417+
{
418+
true
419+
} else {
420+
false
421+
};
387422

388423
// While promoteds should mostly be correct by construction, we need to check them for
389424
// invalid moves to detect moving out of arrays:`struct S; fn main() { &([S][0]); }`.
@@ -434,6 +469,26 @@ fn do_mir_borrowck<'tcx>(
434469
promoted_mbcx.report_move_errors();
435470
}
436471

472+
let mut local_names = IndexVec::from_elem(None, &body.local_decls);
473+
for var_debug_info in &body.var_debug_info {
474+
if let VarDebugInfoContents::Place(place) = var_debug_info.value {
475+
if let Some(local) = place.as_local() {
476+
if let Some(prev_name) = local_names[local]
477+
&& var_debug_info.name != prev_name
478+
{
479+
span_bug!(
480+
var_debug_info.source_info.span,
481+
"local {:?} has many names (`{}` vs `{}`)",
482+
local,
483+
prev_name,
484+
var_debug_info.name
485+
);
486+
}
487+
local_names[local] = Some(var_debug_info.name);
488+
}
489+
}
490+
}
491+
437492
let mut mbcx = MirBorrowckCtxt {
438493
root_cx,
439494
infcx: &infcx,

0 commit comments

Comments
 (0)