Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 8565895

Browse files
committed
Auto merge of rust-lang#138499 - lcnr:borrowck-typeck_root, r=<try>
borrowck typeck children together with their root This introduces new cycle errors, even with `feature(inline_const_pat)` removed, see the `non-structural-match-types-cycle-err.rs` test. The new cycle error happens as the layout of `async`-blocks relies on their `optimized_mir`. As that now depends on `mir_borrowck` of its typeck parent, computing the layout of an `async`-block during MIR building, e.g. when evaluating a named `const` pattern. I think there's currently no way to have a named const pattern whose type references an async block while being allowed? cc `@oli-obk` `@RalfJung` I cannot think of other cases where we currently rely on the MIR of a typeck children while borrowchecking their parent. The crater run came back without any breakage. My work here will prevent any future features which rely on this as we'll get locked into borrowchecking them together as I continue to work on rust-lang/types-team#129, cc `@rust-lang/types.` r? compiler-errors
2 parents 79de6c0 + 48a3c5e commit 8565895

File tree

19 files changed

+319
-200
lines changed

19 files changed

+319
-200
lines changed

compiler/rustc_borrowck/src/consumers.rs

Lines changed: 4 additions & 2 deletions
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

Lines changed: 57 additions & 45 deletions
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

Lines changed: 6 additions & 13 deletions
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

Lines changed: 0 additions & 55 deletions
This file was deleted.

0 commit comments

Comments
 (0)