Skip to content

Commit 5020dbc

Browse files
committed
borrowck typeck children together with their parent
1 parent c847755 commit 5020dbc

File tree

19 files changed

+324
-204
lines changed

19 files changed

+324
-204
lines changed

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
}

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);
@@ -191,13 +212,13 @@ fn do_mir_borrowck<'tcx>(
191212
// Compute non-lexical lifetimes.
192213
let nll::NllOutput {
193214
regioncx,
194-
concrete_opaque_types,
195215
polonius_input,
196216
polonius_output,
197217
opt_closure_req,
198218
nll_errors,
199219
polonius_diagnostics,
200220
} = nll::compute_regions(
221+
root_cx,
201222
&infcx,
202223
free_regions,
203224
body,
@@ -216,26 +237,19 @@ fn do_mir_borrowck<'tcx>(
216237
// We also have a `#[rustc_regions]` annotation that causes us to dump
217238
// information.
218239
let diags_buffer = &mut BorrowckDiagnosticsBuffer::default();
219-
nll::dump_annotation(
220-
&infcx,
221-
body,
222-
&regioncx,
223-
&opt_closure_req,
224-
&concrete_opaque_types,
225-
diags_buffer,
226-
);
240+
nll::dump_annotation(&infcx, body, &regioncx, &opt_closure_req, diags_buffer);
227241

228242
let movable_coroutine =
229-
// The first argument is the coroutine type passed by value
230-
if let Some(local) = body.local_decls.raw.get(1)
231-
// Get the interior types and args which typeck computed
232-
&& let ty::Coroutine(def_id, _) = *local.ty.kind()
233-
&& tcx.coroutine_movability(def_id) == hir::Movability::Movable
234-
{
235-
true
236-
} else {
237-
false
238-
};
243+
// The first argument is the coroutine type passed by value
244+
if let Some(local) = body.local_decls.raw.get(1)
245+
// Get the interior types and args which typeck computed
246+
&& let ty::Coroutine(def_id, _) = *local.ty.kind()
247+
&& tcx.coroutine_movability(def_id) == hir::Movability::Movable
248+
{
249+
true
250+
} else {
251+
false
252+
};
239253

240254
// While promoteds should mostly be correct by construction, we need to check them for
241255
// invalid moves to detect moving out of arrays:`struct S; fn main() { &([S][0]); }`.
@@ -246,6 +260,7 @@ fn do_mir_borrowck<'tcx>(
246260
// this check out of `MirBorrowckCtxt`, actually doing so is far from trivial.
247261
let move_data = MoveData::gather_moves(promoted_body, tcx, |_| true);
248262
let mut promoted_mbcx = MirBorrowckCtxt {
263+
root_cx,
249264
infcx: &infcx,
250265
body: promoted_body,
251266
move_data: &move_data,
@@ -286,6 +301,7 @@ fn do_mir_borrowck<'tcx>(
286301
}
287302

288303
let mut mbcx = MirBorrowckCtxt {
304+
root_cx,
289305
infcx: &infcx,
290306
body,
291307
move_data: &move_data,
@@ -353,13 +369,13 @@ fn do_mir_borrowck<'tcx>(
353369

354370
debug!("mbcx.used_mut: {:?}", mbcx.used_mut);
355371
mbcx.lint_unused_mut();
356-
let tainted_by_errors = mbcx.emit_errors();
372+
if let Some(guar) = mbcx.emit_errors() {
373+
mbcx.root_cx.set_tainted_by_errors(guar);
374+
}
357375

358-
let result = BorrowCheckResult {
359-
concrete_opaque_types: concrete_opaque_types.into_inner(),
376+
let result = PropagatedBorrowCheckResults {
360377
closure_requirements: opt_closure_req,
361378
used_mut_upvars: mbcx.used_mut_upvars,
362-
tainted_by_errors,
363379
};
364380

365381
let body_with_facts = if consumer_options.is_some() {
@@ -512,6 +528,7 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {
512528
}
513529

514530
struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
531+
root_cx: &'a mut BorrowCheckRootCtxt<'tcx>,
515532
infcx: &'infcx BorrowckInferCtxt<'tcx>,
516533
body: &'a Body<'tcx>,
517534
move_data: &'a MoveData<'tcx>,
@@ -1385,11 +1402,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
13851402
| AggregateKind::CoroutineClosure(def_id, _)
13861403
| AggregateKind::Coroutine(def_id, _) => {
13871404
let def_id = def_id.expect_local();
1388-
let BorrowCheckResult { used_mut_upvars, .. } =
1389-
self.infcx.tcx.mir_borrowck(def_id);
1405+
let used_mut_upvars = self.root_cx.used_mut_upvars(def_id);
13901406
debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars);
1391-
for field in used_mut_upvars {
1392-
self.propagate_closure_used_mut_upvar(&operands[*field]);
1407+
// FIXME: We're cloning the `SmallVec` here to avoid borrowing `root_cx`
1408+
// when calling `propagate_closure_used_mut_upvar`. This should ideally
1409+
// be unnecessary.
1410+
for field in used_mut_upvars.clone() {
1411+
self.propagate_closure_used_mut_upvar(&operands[field]);
13931412
}
13941413
}
13951414
AggregateKind::Adt(..)

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)