Skip to content

Commit a46bab5

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

File tree

19 files changed

+310
-200
lines changed

19 files changed

+310
-200
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

+57-45
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,57 @@ pub fn provide(providers: &mut Providers) {
102103
*providers = Providers { mir_borrowck, ..*providers };
103104
}
104105

105-
fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
106+
fn mir_borrowck(
107+
tcx: TyCtxt<'_>,
108+
def: LocalDefId,
109+
) -> Result<&ConcreteOpaqueTypes<'_>, ErrorGuaranteed> {
110+
assert!(!tcx.is_typeck_child(def.to_def_id()));
106111
let (input_body, _) = tcx.mir_promoted(def);
112+
debug!("run query mir_borrowck: {}", tcx.def_path_str(def));
113+
107114
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);
115+
if let Some(guar) = input_body.tainted_by_errors {
116+
debug!("Skipping borrowck because of tainted body");
117+
Err(guar)
118+
} else if input_body.should_skip() {
119+
debug!("Skipping borrowck because of injected body");
120+
let opaque_types = ConcreteOpaqueTypes(Default::default());
121+
Ok(tcx.arena.alloc(opaque_types))
122+
} else {
123+
let mut root_cx = BorrowCheckRootCtxt::new(tcx, def);
124+
let BorrowCheckResult { closure_requirements, used_mut_upvars } =
125+
do_mir_borrowck(&mut root_cx, def, None).0;
126+
debug_assert!(closure_requirements.is_none());
127+
debug_assert!(used_mut_upvars.is_empty());
128+
root_cx.finalize()
118129
}
130+
}
119131

120-
let borrowck_result = do_mir_borrowck(tcx, def, None).0;
121-
debug!("mir_borrowck done");
122-
123-
tcx.arena.alloc(borrowck_result)
132+
#[derive(Debug)]
133+
struct BorrowCheckResult<'tcx> {
134+
closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
135+
used_mut_upvars: SmallVec<[FieldIdx; 8]>,
124136
}
125137

126138
/// Perform the actual borrow checking.
127139
///
128140
/// Use `consumer_options: None` for the default behavior of returning
129141
/// [`BorrowCheckResult`] only. Otherwise, return [`BodyWithBorrowckFacts`] according
130142
/// to the given [`ConsumerOptions`].
131-
#[instrument(skip(tcx), level = "debug")]
143+
#[instrument(skip(root_cx), level = "debug")]
132144
fn do_mir_borrowck<'tcx>(
133-
tcx: TyCtxt<'tcx>,
145+
root_cx: &mut BorrowCheckRootCtxt<'tcx>,
134146
def: LocalDefId,
135147
consumer_options: Option<ConsumerOptions>,
136148
) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
149+
let tcx = root_cx.tcx;
137150
let infcx = BorrowckInferCtxt::new(tcx, def);
138151
let (input_body, promoted) = tcx.mir_promoted(def);
139152
let input_body: &Body<'_> = &input_body.borrow();
140153
let input_promoted: &IndexSlice<_, _> = &promoted.borrow();
141154
if let Some(e) = input_body.tainted_by_errors {
142155
infcx.set_tainted_by_errors(e);
156+
root_cx.set_tainted_by_errors(e);
143157
}
144158

145159
let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
@@ -191,13 +205,13 @@ fn do_mir_borrowck<'tcx>(
191205
// Compute non-lexical lifetimes.
192206
let nll::NllOutput {
193207
regioncx,
194-
concrete_opaque_types,
195208
polonius_input,
196209
polonius_output,
197210
opt_closure_req,
198211
nll_errors,
199212
polonius_diagnostics,
200213
} = nll::compute_regions(
214+
root_cx,
201215
&infcx,
202216
free_regions,
203217
body,
@@ -216,26 +230,19 @@ fn do_mir_borrowck<'tcx>(
216230
// We also have a `#[rustc_regions]` annotation that causes us to dump
217231
// information.
218232
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-
);
233+
nll::dump_annotation(&infcx, body, &regioncx, &opt_closure_req, diags_buffer);
227234

228235
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-
};
236+
// The first argument is the coroutine type passed by value
237+
if let Some(local) = body.local_decls.raw.get(1)
238+
// Get the interior types and args which typeck computed
239+
&& let ty::Coroutine(def_id, _) = *local.ty.kind()
240+
&& tcx.coroutine_movability(def_id) == hir::Movability::Movable
241+
{
242+
true
243+
} else {
244+
false
245+
};
239246

240247
// While promoteds should mostly be correct by construction, we need to check them for
241248
// invalid moves to detect moving out of arrays:`struct S; fn main() { &([S][0]); }`.
@@ -246,6 +253,7 @@ fn do_mir_borrowck<'tcx>(
246253
// this check out of `MirBorrowckCtxt`, actually doing so is far from trivial.
247254
let move_data = MoveData::gather_moves(promoted_body, tcx, |_| true);
248255
let mut promoted_mbcx = MirBorrowckCtxt {
256+
root_cx,
249257
infcx: &infcx,
250258
body: promoted_body,
251259
move_data: &move_data,
@@ -286,6 +294,7 @@ fn do_mir_borrowck<'tcx>(
286294
}
287295

288296
let mut mbcx = MirBorrowckCtxt {
297+
root_cx,
289298
infcx: &infcx,
290299
body,
291300
move_data: &move_data,
@@ -353,13 +362,13 @@ fn do_mir_borrowck<'tcx>(
353362

354363
debug!("mbcx.used_mut: {:?}", mbcx.used_mut);
355364
mbcx.lint_unused_mut();
356-
let tainted_by_errors = mbcx.emit_errors();
365+
if let Some(guar) = mbcx.emit_errors() {
366+
mbcx.root_cx.set_tainted_by_errors(guar);
367+
}
357368

358369
let result = BorrowCheckResult {
359-
concrete_opaque_types: concrete_opaque_types.into_inner(),
360370
closure_requirements: opt_closure_req,
361371
used_mut_upvars: mbcx.used_mut_upvars,
362-
tainted_by_errors,
363372
};
364373

365374
let body_with_facts = if consumer_options.is_some() {
@@ -512,6 +521,7 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {
512521
}
513522

514523
struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
524+
root_cx: &'a mut BorrowCheckRootCtxt<'tcx>,
515525
infcx: &'infcx BorrowckInferCtxt<'tcx>,
516526
body: &'a Body<'tcx>,
517527
move_data: &'a MoveData<'tcx>,
@@ -1385,11 +1395,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
13851395
| AggregateKind::CoroutineClosure(def_id, _)
13861396
| AggregateKind::Coroutine(def_id, _) => {
13871397
let def_id = def_id.expect_local();
1388-
let BorrowCheckResult { used_mut_upvars, .. } =
1389-
self.infcx.tcx.mir_borrowck(def_id);
1398+
let used_mut_upvars = self.root_cx.used_mut_upvars(def_id);
13901399
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]);
1400+
// FIXME: We're cloning the `SmallVec` here to avoid borrowing `root_cx`
1401+
// when calling `propagate_closure_used_mut_upvar`. This should ideally
1402+
// be unnecessary.
1403+
for field in used_mut_upvars.clone() {
1404+
self.propagate_closure_used_mut_upvar(&operands[field]);
13931405
}
13941406
}
13951407
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
}

compiler/rustc_borrowck/src/opaque_types.rs

-55
This file was deleted.

0 commit comments

Comments
 (0)