Skip to content

Commit f05a23b

Browse files
committed
borrowck typeck children together with their parent
1 parent e643f59 commit f05a23b

File tree

19 files changed

+335
-217
lines changed

19 files changed

+335
-217
lines changed

Diff for: compiler/rustc_borrowck/src/consumers.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +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};
1819

1920
/// Options determining the output behavior of [`get_body_with_borrowck_facts`].
2021
///
@@ -97,8 +98,9 @@ pub struct BodyWithBorrowckFacts<'tcx> {
9798
/// * Polonius is highly unstable, so expect regular changes in its signature or other details.
9899
pub fn get_body_with_borrowck_facts(
99100
tcx: TyCtxt<'_>,
100-
def: LocalDefId,
101+
def_id: LocalDefId,
101102
options: ConsumerOptions,
102103
) -> BodyWithBorrowckFacts<'_> {
103-
*super::do_mir_borrowck(tcx, def, Some(options)).1.unwrap()
104+
let mut root_cx = BorrowCheckRootCtxt::new(tcx, def_id);
105+
*do_mir_borrowck(&mut root_cx, def_id, Some(options)).1.unwrap()
104106
}

Diff for: compiler/rustc_borrowck/src/lib.rs

+68-49
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use std::cell::RefCell;
2121
use std::marker::PhantomData;
2222
use std::ops::{ControlFlow, Deref};
2323

24+
use root_cx::BorrowCheckRootCtxt;
2425
use rustc_abi::FieldIdx;
2526
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
2627
use rustc_data_structures::graph::dominators::Dominators;
@@ -45,7 +46,7 @@ use rustc_mir_dataflow::move_paths::{
4546
};
4647
use rustc_mir_dataflow::{Analysis, EntryStates, Results, ResultsVisitor, visit_results};
4748
use rustc_session::lint::builtin::{TAIL_EXPR_DROP_ORDER, UNUSED_MUT};
48-
use rustc_span::{Span, Symbol};
49+
use rustc_span::{ErrorGuaranteed, Span, Symbol};
4950
use smallvec::SmallVec;
5051
use tracing::{debug, instrument};
5152

@@ -73,14 +74,14 @@ mod def_use;
7374
mod diagnostics;
7475
mod member_constraints;
7576
mod nll;
76-
mod opaque_types;
7777
mod path_utils;
7878
mod place_ext;
7979
mod places_conflict;
8080
mod polonius;
8181
mod prefixes;
8282
mod region_infer;
8383
mod renumber;
84+
mod root_cx;
8485
mod session_diagnostics;
8586
mod type_check;
8687
mod universal_regions;
@@ -102,44 +103,64 @@ pub fn provide(providers: &mut Providers) {
102103
*providers = Providers { mir_borrowck, ..*providers };
103104
}
104105

105-
fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
106+
/// Provider for `query mir_borrowck`. Similar to `typeck`, this must
107+
/// only be called for typeck roots which will then borrowck all
108+
/// nested bodies as well.
109+
fn mir_borrowck(
110+
tcx: TyCtxt<'_>,
111+
def: LocalDefId,
112+
) -> Result<&ConcreteOpaqueTypes<'_>, ErrorGuaranteed> {
113+
assert!(!tcx.is_typeck_child(def.to_def_id()));
106114
let (input_body, _) = tcx.mir_promoted(def);
115+
debug!("run query mir_borrowck: {}", tcx.def_path_str(def));
116+
107117
let input_body: &Body<'_> = &input_body.borrow();
108-
if input_body.should_skip() || input_body.tainted_by_errors.is_some() {
109-
debug!("Skipping borrowck because of injected body or tainted body");
110-
// Let's make up a borrowck result! Fun times!
111-
let result = BorrowCheckResult {
112-
concrete_opaque_types: FxIndexMap::default(),
113-
closure_requirements: None,
114-
used_mut_upvars: SmallVec::new(),
115-
tainted_by_errors: input_body.tainted_by_errors,
116-
};
117-
return tcx.arena.alloc(result);
118+
if let Some(guar) = input_body.tainted_by_errors {
119+
debug!("Skipping borrowck because of tainted body");
120+
Err(guar)
121+
} else if input_body.should_skip() {
122+
debug!("Skipping borrowck because of injected body");
123+
let opaque_types = ConcreteOpaqueTypes(Default::default());
124+
Ok(tcx.arena.alloc(opaque_types))
125+
} else {
126+
let mut root_cx = BorrowCheckRootCtxt::new(tcx, def);
127+
let PropagatedBorrowCheckResults { closure_requirements, used_mut_upvars } =
128+
do_mir_borrowck(&mut root_cx, def, None).0;
129+
debug_assert!(closure_requirements.is_none());
130+
debug_assert!(used_mut_upvars.is_empty());
131+
root_cx.finalize()
118132
}
133+
}
119134

120-
let borrowck_result = do_mir_borrowck(tcx, def, None).0;
121-
debug!("mir_borrowck done");
122-
123-
tcx.arena.alloc(borrowck_result)
135+
/// Data propagated to the typeck parent by nested items.
136+
/// This should always be empty for the typeck root.
137+
#[derive(Debug)]
138+
struct PropagatedBorrowCheckResults<'tcx> {
139+
closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
140+
used_mut_upvars: SmallVec<[FieldIdx; 8]>,
124141
}
125142

126143
/// Perform the actual borrow checking.
127144
///
128145
/// Use `consumer_options: None` for the default behavior of returning
129-
/// [`BorrowCheckResult`] only. Otherwise, return [`BodyWithBorrowckFacts`] according
130-
/// to the given [`ConsumerOptions`].
131-
#[instrument(skip(tcx), level = "debug")]
146+
/// [`PropagatedBorrowCheckResults`] only. Otherwise, return [`BodyWithBorrowckFacts`]
147+
/// according to the given [`ConsumerOptions`].
148+
///
149+
/// For nested bodies this should only be called through `root_cx.get_or_insert_nested`.
150+
#[instrument(skip(root_cx), level = "debug")]
132151
fn do_mir_borrowck<'tcx>(
133-
tcx: TyCtxt<'tcx>,
152+
root_cx: &mut BorrowCheckRootCtxt<'tcx>,
134153
def: LocalDefId,
135154
consumer_options: Option<ConsumerOptions>,
136-
) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
155+
) -> (PropagatedBorrowCheckResults<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
156+
let tcx = root_cx.tcx;
137157
let infcx = BorrowckInferCtxt::new(tcx, def);
138158
let (input_body, promoted) = tcx.mir_promoted(def);
139159
let input_body: &Body<'_> = &input_body.borrow();
140160
let input_promoted: &IndexSlice<_, _> = &promoted.borrow();
141161
if let Some(e) = input_body.tainted_by_errors {
142162
infcx.set_tainted_by_errors(e);
163+
root_cx.set_tainted_by_errors(e);
143164
}
144165

145166
let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
@@ -185,13 +206,13 @@ fn do_mir_borrowck<'tcx>(
185206
// Compute non-lexical lifetimes.
186207
let nll::NllOutput {
187208
regioncx,
188-
concrete_opaque_types,
189209
polonius_input,
190210
polonius_output,
191211
opt_closure_req,
192212
nll_errors,
193213
polonius_diagnostics,
194214
} = nll::compute_regions(
215+
root_cx,
195216
&infcx,
196217
free_regions,
197218
body,
@@ -210,26 +231,19 @@ fn do_mir_borrowck<'tcx>(
210231
// We also have a `#[rustc_regions]` annotation that causes us to dump
211232
// information.
212233
let diags_buffer = &mut BorrowckDiagnosticsBuffer::default();
213-
nll::dump_annotation(
214-
&infcx,
215-
body,
216-
&regioncx,
217-
&opt_closure_req,
218-
&concrete_opaque_types,
219-
diags_buffer,
220-
);
234+
nll::dump_annotation(&infcx, body, &regioncx, &opt_closure_req, diags_buffer);
221235

222236
let movable_coroutine =
223-
// The first argument is the coroutine type passed by value
224-
if let Some(local) = body.local_decls.raw.get(1)
225-
// Get the interior types and args which typeck computed
226-
&& let ty::Coroutine(def_id, _) = *local.ty.kind()
227-
&& tcx.coroutine_movability(def_id) == hir::Movability::Movable
228-
{
229-
true
230-
} else {
231-
false
232-
};
237+
// The first argument is the coroutine type passed by value
238+
if let Some(local) = body.local_decls.raw.get(1)
239+
// Get the interior types and args which typeck computed
240+
&& let ty::Coroutine(def_id, _) = *local.ty.kind()
241+
&& tcx.coroutine_movability(def_id) == hir::Movability::Movable
242+
{
243+
true
244+
} else {
245+
false
246+
};
233247

234248
// While promoteds should mostly be correct by construction, we need to check them for
235249
// invalid moves to detect moving out of arrays:`struct S; fn main() { &([S][0]); }`.
@@ -240,6 +254,7 @@ fn do_mir_borrowck<'tcx>(
240254
// this check out of `MirBorrowckCtxt`, actually doing so is far from trivial.
241255
let move_data = MoveData::gather_moves(promoted_body, tcx, |_| true);
242256
let mut promoted_mbcx = MirBorrowckCtxt {
257+
root_cx,
243258
infcx: &infcx,
244259
body: promoted_body,
245260
move_data: &move_data,
@@ -280,6 +295,7 @@ fn do_mir_borrowck<'tcx>(
280295
}
281296

282297
let mut mbcx = MirBorrowckCtxt {
298+
root_cx,
283299
infcx: &infcx,
284300
body,
285301
move_data: &move_data,
@@ -347,13 +363,13 @@ fn do_mir_borrowck<'tcx>(
347363

348364
debug!("mbcx.used_mut: {:?}", mbcx.used_mut);
349365
mbcx.lint_unused_mut();
350-
let tainted_by_errors = mbcx.emit_errors();
366+
if let Some(guar) = mbcx.emit_errors() {
367+
mbcx.root_cx.set_tainted_by_errors(guar);
368+
}
351369

352-
let result = BorrowCheckResult {
353-
concrete_opaque_types: concrete_opaque_types.into_inner(),
370+
let result = PropagatedBorrowCheckResults {
354371
closure_requirements: opt_closure_req,
355372
used_mut_upvars: mbcx.used_mut_upvars,
356-
tainted_by_errors,
357373
};
358374

359375
let body_with_facts = if consumer_options.is_some() {
@@ -488,6 +504,7 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {
488504
}
489505

490506
struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
507+
root_cx: &'a mut BorrowCheckRootCtxt<'tcx>,
491508
infcx: &'infcx BorrowckInferCtxt<'tcx>,
492509
body: &'a Body<'tcx>,
493510
move_data: &'a MoveData<'tcx>,
@@ -1361,11 +1378,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
13611378
| AggregateKind::CoroutineClosure(def_id, _)
13621379
| AggregateKind::Coroutine(def_id, _) => {
13631380
let def_id = def_id.expect_local();
1364-
let BorrowCheckResult { used_mut_upvars, .. } =
1365-
self.infcx.tcx.mir_borrowck(def_id);
1381+
let used_mut_upvars = self.root_cx.used_mut_upvars(def_id);
13661382
debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars);
1367-
for field in used_mut_upvars {
1368-
self.propagate_closure_used_mut_upvar(&operands[*field]);
1383+
// FIXME: We're cloning the `SmallVec` here to avoid borrowing `root_cx`
1384+
// when calling `propagate_closure_used_mut_upvar`. This should ideally
1385+
// be unnecessary.
1386+
for field in used_mut_upvars.clone() {
1387+
self.propagate_closure_used_mut_upvar(&operands[field]);
13691388
}
13701389
}
13711390
AggregateKind::Adt(..)

Diff for: compiler/rustc_borrowck/src/nll.rs

+6-13
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,19 @@ use tracing::{debug, instrument};
2525
use crate::borrow_set::BorrowSet;
2626
use crate::consumers::ConsumerOptions;
2727
use crate::diagnostics::{BorrowckDiagnosticsBuffer, RegionErrors};
28-
use crate::opaque_types::ConcreteOpaqueTypes;
2928
use crate::polonius::PoloniusDiagnosticsContext;
3029
use crate::polonius::legacy::{
3130
PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput,
3231
};
3332
use crate::region_infer::RegionInferenceContext;
3433
use crate::type_check::{self, MirTypeckResults};
3534
use crate::universal_regions::UniversalRegions;
36-
use crate::{BorrowckInferCtxt, polonius, renumber};
35+
use crate::{BorrowCheckRootCtxt, BorrowckInferCtxt, polonius, renumber};
3736

3837
/// The output of `nll::compute_regions`. This includes the computed `RegionInferenceContext`, any
3938
/// closure requirements to propagate, and any generated errors.
4039
pub(crate) struct NllOutput<'tcx> {
4140
pub regioncx: RegionInferenceContext<'tcx>,
42-
pub concrete_opaque_types: ConcreteOpaqueTypes<'tcx>,
4341
pub polonius_input: Option<Box<PoloniusFacts>>,
4442
pub polonius_output: Option<Box<PoloniusOutput>>,
4543
pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>,
@@ -78,6 +76,7 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
7876
///
7977
/// This may result in errors being reported.
8078
pub(crate) fn compute_regions<'a, 'tcx>(
79+
root_cx: &mut BorrowCheckRootCtxt<'tcx>,
8180
infcx: &BorrowckInferCtxt<'tcx>,
8281
universal_regions: UniversalRegions<'tcx>,
8382
body: &Body<'tcx>,
@@ -98,15 +97,14 @@ pub(crate) fn compute_regions<'a, 'tcx>(
9897

9998
let location_map = Rc::new(DenseLocationMap::new(body));
10099

101-
let mut concrete_opaque_types = ConcreteOpaqueTypes::default();
102-
103100
// Run the MIR type-checker.
104101
let MirTypeckResults {
105102
constraints,
106103
universal_region_relations,
107104
opaque_type_values,
108105
polonius_context,
109106
} = type_check::type_check(
107+
root_cx,
110108
infcx,
111109
body,
112110
promoted,
@@ -117,7 +115,6 @@ pub(crate) fn compute_regions<'a, 'tcx>(
117115
flow_inits,
118116
move_data,
119117
Rc::clone(&location_map),
120-
&mut concrete_opaque_types,
121118
);
122119

123120
// Create the region inference context, taking ownership of the
@@ -181,11 +178,10 @@ pub(crate) fn compute_regions<'a, 'tcx>(
181178
infcx.set_tainted_by_errors(guar);
182179
}
183180

184-
regioncx.infer_opaque_types(infcx, opaque_type_values, &mut concrete_opaque_types);
181+
regioncx.infer_opaque_types(root_cx, infcx, opaque_type_values);
185182

186183
NllOutput {
187184
regioncx,
188-
concrete_opaque_types,
189185
polonius_input: polonius_facts.map(Box::new),
190186
polonius_output,
191187
opt_closure_req: closure_region_requirements,
@@ -301,7 +297,6 @@ pub(super) fn dump_annotation<'tcx, 'infcx>(
301297
body: &Body<'tcx>,
302298
regioncx: &RegionInferenceContext<'tcx>,
303299
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
304-
concrete_opaque_types: &ConcreteOpaqueTypes<'tcx>,
305300
diagnostics_buffer: &mut BorrowckDiagnosticsBuffer<'infcx, 'tcx>,
306301
) {
307302
let tcx = infcx.tcx;
@@ -318,7 +313,7 @@ pub(super) fn dump_annotation<'tcx, 'infcx>(
318313
// better.
319314

320315
let def_span = tcx.def_span(body.source.def_id());
321-
let mut err = if let Some(closure_region_requirements) = closure_region_requirements {
316+
let err = if let Some(closure_region_requirements) = closure_region_requirements {
322317
let mut err = infcx.dcx().struct_span_note(def_span, "external requirements");
323318

324319
regioncx.annotate(tcx, &mut err);
@@ -344,9 +339,7 @@ pub(super) fn dump_annotation<'tcx, 'infcx>(
344339
err
345340
};
346341

347-
if !concrete_opaque_types.is_empty() {
348-
err.note(format!("Inferred opaque type values:\n{concrete_opaque_types:#?}"));
349-
}
342+
// FIXME(@lcnr): We currently don't dump the inferred hidden types here.
350343

351344
diagnostics_buffer.buffer_non_error(err);
352345
}

0 commit comments

Comments
 (0)