Skip to content

Commit 6290ae9

Browse files
committed
Auto merge of #108487 - cjgillot:no-typeck-mir, r=oli-obk
Avoid invoking typeck from borrowck This PR attempts to reduce direct dependencies between typeck and MIR-related queries. The goal is to have all the information transit either through THIR or through dedicated queries that avoid depending on the whole `TypeckResults`. In a first commit, we store the type information that MIR building requires into THIR. This avoids edges between mir_built and typeck. In the second and third commit, we wrap informations around closures (upvars, kind origin and user-provided signature) to avoid borrowck depending on typeck information. There should be a single remaining borrowck -> typeck edge in the good path, due to inline consts.
2 parents 7281249 + cb51d2d commit 6290ae9

File tree

20 files changed

+223
-207
lines changed

20 files changed

+223
-207
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+6-17
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_errors::{
66
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
77
};
88
use rustc_hir as hir;
9-
use rustc_hir::def::Res;
9+
use rustc_hir::def::{DefKind, Res};
1010
use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
1111
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem};
1212
use rustc_infer::infer::TyCtxtInferExt;
@@ -236,10 +236,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
236236
let ty = used_place.ty(self.body, self.infcx.tcx).ty;
237237
let needs_note = match ty.kind() {
238238
ty::Closure(id, _) => {
239-
let tables = self.infcx.tcx.typeck(id.expect_local());
240-
let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(id.expect_local());
241-
242-
tables.closure_kind_origins().get(hir_id).is_none()
239+
self.infcx.tcx.closure_kind_origin(id.expect_local()).is_none()
243240
}
244241
_ => true,
245242
};
@@ -1670,27 +1667,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
16701667
format!("`{}` would have to be valid for `{}`...", name, region_name),
16711668
);
16721669

1673-
let fn_hir_id = self.mir_hir_id();
16741670
err.span_label(
16751671
drop_span,
16761672
format!(
16771673
"...but `{}` will be dropped here, when the {} returns",
16781674
name,
16791675
self.infcx
16801676
.tcx
1681-
.hir()
1682-
.opt_name(fn_hir_id)
1677+
.opt_item_name(self.mir_def_id().to_def_id())
16831678
.map(|name| format!("function `{}`", name))
16841679
.unwrap_or_else(|| {
1685-
match &self
1686-
.infcx
1687-
.tcx
1688-
.typeck(self.mir_def_id())
1689-
.node_type(fn_hir_id)
1690-
.kind()
1691-
{
1692-
ty::Closure(..) => "enclosing closure",
1693-
ty::Generator(..) => "enclosing generator",
1680+
match &self.infcx.tcx.def_kind(self.mir_def_id()) {
1681+
DefKind::Closure => "enclosing closure",
1682+
DefKind::Generator => "enclosing generator",
16941683
kind => bug!("expected closure or generator, found {:?}", kind),
16951684
}
16961685
.to_string()

compiler/rustc_borrowck/src/diagnostics/mod.rs

+5-19
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
115115
debug!("add_moved_or_invoked_closure_note: closure={:?}", closure);
116116
if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind() {
117117
let did = did.expect_local();
118-
let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did);
119-
120-
if let Some((span, hir_place)) =
121-
self.infcx.tcx.typeck(did).closure_kind_origins().get(hir_id)
122-
{
118+
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
123119
diag.span_note(
124120
*span,
125121
&format!(
@@ -139,11 +135,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
139135
if let Some(target) = target {
140136
if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind() {
141137
let did = did.expect_local();
142-
let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did);
143-
144-
if let Some((span, hir_place)) =
145-
self.infcx.tcx.typeck(did).closure_kind_origins().get(hir_id)
146-
{
138+
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
147139
diag.span_note(
148140
*span,
149141
&format!(
@@ -373,14 +365,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
373365
//
374366
// We know the field exists so it's safe to call operator[] and `unwrap` here.
375367
let def_id = def_id.expect_local();
376-
let var_id = self
377-
.infcx
378-
.tcx
379-
.typeck(def_id)
380-
.closure_min_captures_flattened(def_id)
381-
.nth(field.index())
382-
.unwrap()
383-
.get_root_variable();
368+
let var_id =
369+
self.infcx.tcx.closure_captures(def_id)[field.index()].get_root_variable();
384370

385371
Some(self.infcx.tcx.hir().name(var_id).to_string())
386372
}
@@ -987,7 +973,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
987973
debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
988974
if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = expr {
989975
for (captured_place, place) in
990-
self.infcx.tcx.typeck(def_id).closure_min_captures_flattened(def_id).zip(places)
976+
self.infcx.tcx.closure_captures(def_id).iter().zip(places)
991977
{
992978
match place {
993979
Operand::Copy(place) | Operand::Move(place)

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -901,10 +901,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
901901
err: &mut Diagnostic,
902902
) {
903903
let tables = tcx.typeck(closure_local_def_id);
904-
let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_local_def_id);
905-
if let Some((span, closure_kind_origin)) =
906-
&tables.closure_kind_origins().get(closure_hir_id)
907-
{
904+
if let Some((span, closure_kind_origin)) = tcx.closure_kind_origin(closure_local_def_id) {
908905
let reason = if let PlaceBase::Upvar(upvar_id) = closure_kind_origin.base {
909906
let upvar = ty::place_to_string_for_capture(tcx, closure_kind_origin);
910907
let root_hir_id = upvar_id.var_path.hir_id;

compiler/rustc_borrowck/src/lib.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -202,14 +202,14 @@ fn do_mir_borrowck<'tcx>(
202202
let mut errors = error::BorrowckErrors::new(infcx.tcx);
203203

204204
// Gather the upvars of a closure, if any.
205-
let tables = tcx.typeck_opt_const_arg(def);
206-
if let Some(e) = tables.tainted_by_errors {
205+
if let Some(e) = input_body.tainted_by_errors {
207206
infcx.set_tainted_by_errors(e);
208207
errors.set_tainted_by_errors(e);
209208
}
210-
let upvars: Vec<_> = tables
211-
.closure_min_captures_flattened(def.did)
212-
.map(|captured_place| {
209+
let upvars: Vec<_> = tcx
210+
.closure_captures(def.did)
211+
.iter()
212+
.map(|&captured_place| {
213213
let capture = captured_place.info.capture_kind;
214214
let by_ref = match capture {
215215
ty::UpvarCapture::ByValue => false,

compiler/rustc_borrowck/src/type_check/input_output.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
2626
if !self.tcx().is_closure(mir_def_id.to_def_id()) {
2727
return;
2828
}
29-
let Some(user_provided_poly_sig) =
30-
self.tcx().typeck(mir_def_id).user_provided_sigs.get(&mir_def_id)
31-
else {
32-
return;
33-
};
29+
let user_provided_poly_sig = self.tcx().closure_user_provided_sig(mir_def_id);
3430

3531
// Instantiate the canonicalized variables from user-provided signature
3632
// (e.g., the `_` in the code above) with fresh variables.

compiler/rustc_borrowck/src/universal_regions.rs

+15-12
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_errors::Diagnostic;
1818
use rustc_hir as hir;
1919
use rustc_hir::def_id::{DefId, LocalDefId};
2020
use rustc_hir::lang_items::LangItem;
21-
use rustc_hir::{BodyOwnerKind, HirId};
21+
use rustc_hir::BodyOwnerKind;
2222
use rustc_index::vec::{Idx, IndexVec};
2323
use rustc_infer::infer::NllRegionVariableOrigin;
2424
use rustc_middle::ty::fold::TypeFoldable;
@@ -231,9 +231,7 @@ impl<'tcx> UniversalRegions<'tcx> {
231231
mir_def: ty::WithOptConstParam<LocalDefId>,
232232
param_env: ty::ParamEnv<'tcx>,
233233
) -> Self {
234-
let tcx = infcx.tcx;
235-
let mir_hir_id = tcx.hir().local_def_id_to_hir_id(mir_def.did);
236-
UniversalRegionsBuilder { infcx, mir_def, mir_hir_id, param_env }.build()
234+
UniversalRegionsBuilder { infcx, mir_def, param_env }.build()
237235
}
238236

239237
/// Given a reference to a closure type, extracts all the values
@@ -390,7 +388,6 @@ impl<'tcx> UniversalRegions<'tcx> {
390388
struct UniversalRegionsBuilder<'cx, 'tcx> {
391389
infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>,
392390
mir_def: ty::WithOptConstParam<LocalDefId>,
393-
mir_hir_id: HirId,
394391
param_env: ty::ParamEnv<'tcx>,
395392
}
396393

@@ -560,12 +557,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
560557

561558
match tcx.hir().body_owner_kind(self.mir_def.did) {
562559
BodyOwnerKind::Closure | BodyOwnerKind::Fn => {
563-
let defining_ty = if self.mir_def.did.to_def_id() == typeck_root_def_id {
564-
tcx.type_of(typeck_root_def_id).subst_identity()
565-
} else {
566-
let tables = tcx.typeck(self.mir_def.did);
567-
tables.node_type(self.mir_hir_id)
568-
};
560+
let defining_ty = tcx.type_of(self.mir_def.def_id_for_type_of()).subst_identity();
569561

570562
debug!("defining_ty (pre-replacement): {:?}", defining_ty);
571563

@@ -594,7 +586,18 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
594586
self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_substs);
595587
DefiningTy::Const(self.mir_def.did.to_def_id(), substs)
596588
} else {
597-
let ty = tcx.typeck(self.mir_def.did).node_type(self.mir_hir_id);
589+
// FIXME this line creates a dependency between borrowck and typeck.
590+
//
591+
// This is required for `AscribeUserType` canonical query, which will call
592+
// `type_of(inline_const_def_id)`. That `type_of` would inject erased lifetimes
593+
// into borrowck, which is ICE #78174.
594+
//
595+
// As a workaround, inline consts have an additional generic param (`ty`
596+
// below), so that `type_of(inline_const_def_id).substs(substs)` uses the
597+
// proper type with NLL infer vars.
598+
let ty = tcx
599+
.typeck(self.mir_def.did)
600+
.node_type(tcx.local_def_id_to_hir_id(self.mir_def.did));
598601
let substs = InlineConstSubsts::new(
599602
tcx,
600603
InlineConstSubstsParts { parent_substs: identity_substs, ty },

compiler/rustc_const_eval/src/interpret/validity.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -240,10 +240,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
240240
// FIXME this should be more descriptive i.e. CapturePlace instead of CapturedVar
241241
// https://github.com/rust-lang/project-rfc-2229/issues/46
242242
if let Some(local_def_id) = def_id.as_local() {
243-
let tables = self.ecx.tcx.typeck(local_def_id);
244-
if let Some(captured_place) =
245-
tables.closure_min_captures_flattened(local_def_id).nth(field)
246-
{
243+
let captures = self.ecx.tcx.closure_captures(local_def_id);
244+
if let Some(captured_place) = captures.get(field) {
247245
// Sometimes the index is beyond the number of upvars (seen
248246
// for a generator).
249247
let var_hir_id = captured_place.get_root_variable();

compiler/rustc_hir_typeck/src/upvar.rs

+3
Original file line numberDiff line numberDiff line change
@@ -526,10 +526,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
526526
PlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
527527
base => bug!("Expected upvar, found={:?}", base),
528528
};
529+
let var_ident = self.tcx.hir().ident(var_hir_id);
529530

530531
let Some(min_cap_list) = root_var_min_capture_list.get_mut(&var_hir_id) else {
531532
let mutability = self.determine_capture_mutability(&typeck_results, &place);
532533
let min_cap_list = vec![ty::CapturedPlace {
534+
var_ident,
533535
place,
534536
info: capture_info,
535537
mutability,
@@ -628,6 +630,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
628630
if !ancestor_found {
629631
let mutability = self.determine_capture_mutability(&typeck_results, &place);
630632
let captured_place = ty::CapturedPlace {
633+
var_ident,
631634
place,
632635
info: updated_capture_info,
633636
mutability,

compiler/rustc_middle/src/arena.rs

+1
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ macro_rules! arena_types {
116116
[] bit_set_u32: rustc_index::bit_set::BitSet<u32>,
117117
[] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>,
118118
[decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap,
119+
[] closure_kind_origin: (rustc_span::Span, rustc_middle::hir::place::Place<'tcx>),
119120
]);
120121
)
121122
}

compiler/rustc_middle/src/hir/map/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,11 @@ impl<'hir> Map<'hir> {
902902
self.opt_ident(id).map(|ident| ident.span)
903903
}
904904

905+
#[inline]
906+
pub fn ident(self, id: HirId) -> Ident {
907+
self.opt_ident(id).unwrap()
908+
}
909+
905910
#[inline]
906911
pub fn opt_name(self, id: HirId) -> Option<Symbol> {
907912
self.opt_ident(id).map(|ident| ident.name)

compiler/rustc_middle/src/query/mod.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -475,14 +475,10 @@ rustc_queries! {
475475
}
476476
}
477477

478-
query symbols_for_closure_captures(
479-
key: (LocalDefId, LocalDefId)
480-
) -> &'tcx Vec<rustc_span::Symbol> {
481-
arena_cache
478+
query closure_typeinfo(key: LocalDefId) -> ty::ClosureTypeInfo<'tcx> {
482479
desc {
483-
|tcx| "finding symbols for captures of closure `{}` in `{}`",
484-
tcx.def_path_str(key.1.to_def_id()),
485-
tcx.def_path_str(key.0.to_def_id())
480+
|tcx| "finding symbols for captures of closure `{}`",
481+
tcx.def_path_str(key.to_def_id())
486482
}
487483
}
488484

compiler/rustc_middle/src/thir.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_middle::mir::interpret::AllocId;
2020
use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp};
2121
use rustc_middle::ty::adjustment::PointerCast;
2222
use rustc_middle::ty::subst::SubstsRef;
23-
use rustc_middle::ty::{self, AdtDef, Ty, UpvarSubsts};
23+
use rustc_middle::ty::{self, AdtDef, FnSig, Ty, UpvarSubsts};
2424
use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
2525
use rustc_span::def_id::LocalDefId;
2626
use rustc_span::{sym, Span, Symbol, DUMMY_SP};
@@ -32,7 +32,12 @@ use std::ops::Index;
3232
pub mod visit;
3333

3434
macro_rules! thir_with_elements {
35-
($($name:ident: $id:ty => $value:ty => $format:literal,)*) => {
35+
(
36+
$($field_name:ident: $field_ty:ty,)*
37+
38+
@elements:
39+
$($name:ident: $id:ty => $value:ty => $format:literal,)*
40+
) => {
3641
$(
3742
newtype_index! {
3843
#[derive(HashStable)]
@@ -46,14 +51,20 @@ macro_rules! thir_with_elements {
4651
/// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
4752
#[derive(Debug, HashStable, Clone)]
4853
pub struct Thir<'tcx> {
54+
$(
55+
pub $field_name: $field_ty,
56+
)*
4957
$(
5058
pub $name: IndexVec<$id, $value>,
5159
)*
5260
}
5361

5462
impl<'tcx> Thir<'tcx> {
55-
pub fn new() -> Thir<'tcx> {
63+
pub fn new($($field_name: $field_ty,)*) -> Thir<'tcx> {
5664
Thir {
65+
$(
66+
$field_name,
67+
)*
5768
$(
5869
$name: IndexVec::new(),
5970
)*
@@ -75,13 +86,22 @@ macro_rules! thir_with_elements {
7586
pub const UPVAR_ENV_PARAM: ParamId = ParamId::from_u32(0);
7687

7788
thir_with_elements! {
89+
body_type: BodyTy<'tcx>,
90+
91+
@elements:
7892
arms: ArmId => Arm<'tcx> => "a{}",
7993
blocks: BlockId => Block => "b{}",
8094
exprs: ExprId => Expr<'tcx> => "e{}",
8195
stmts: StmtId => Stmt<'tcx> => "s{}",
8296
params: ParamId => Param<'tcx> => "p{}",
8397
}
8498

99+
#[derive(Debug, HashStable, Clone)]
100+
pub enum BodyTy<'tcx> {
101+
Const(Ty<'tcx>),
102+
Fn(FnSig<'tcx>),
103+
}
104+
85105
/// Description of a type-checked function parameter.
86106
#[derive(Clone, Debug, HashStable)]
87107
pub struct Param<'tcx> {

0 commit comments

Comments
 (0)