Skip to content

Commit 3503f56

Browse files
committed
Auto merge of #73751 - eddyb:no-empty-tables, r=nikomatsakis
Remove `TypeckTables::empty(None)` and make hir_owner non-optional. Each commit before the last one removes uses of `TypeckTables::empty(None)`, replacing the empty tables with having `Option` around the `&'tcx TypeckTables<'tcx>` that HIR visitors kept track of. The last commit removes the concept of "empty `TypeckTables`" altogether, guaranteeing that every `TypeckTables` corresponds to a HIR body owner. r? @nikomatsakis
2 parents 8a6d434 + 4b2d9e6 commit 3503f56

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+355
-371
lines changed

src/librustc_driver/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
77
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
88
#![feature(nll)]
9+
#![cfg_attr(bootstrap, feature(track_caller))]
910
#![recursion_limit = "256"]
1011

1112
#[macro_use]

src/librustc_driver/pretty.rs

+19-10
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ where
8080
PpmTyped => {
8181
abort_on_err(tcx.analysis(LOCAL_CRATE), tcx.sess);
8282

83-
let empty_tables = ty::TypeckTables::empty(None);
84-
let annotation = TypedAnnotation { tcx, tables: Cell::new(&empty_tables) };
83+
let annotation = TypedAnnotation { tcx, maybe_typeck_tables: Cell::new(None) };
8584
tcx.dep_graph.with_ignore(|| f(&annotation, tcx.hir().krate()))
8685
}
8786
_ => panic!("Should use call_with_pp_support"),
@@ -304,12 +303,22 @@ impl<'a> pprust::PpAnn for HygieneAnnotation<'a> {
304303
}
305304
}
306305

307-
struct TypedAnnotation<'a, 'tcx> {
306+
struct TypedAnnotation<'tcx> {
308307
tcx: TyCtxt<'tcx>,
309-
tables: Cell<&'a ty::TypeckTables<'tcx>>,
308+
maybe_typeck_tables: Cell<Option<&'tcx ty::TypeckTables<'tcx>>>,
310309
}
311310

312-
impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> {
311+
impl<'tcx> TypedAnnotation<'tcx> {
312+
/// Gets the type-checking side-tables for the current body.
313+
/// As this will ICE if called outside bodies, only call when working with
314+
/// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
315+
#[track_caller]
316+
fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> {
317+
self.maybe_typeck_tables.get().expect("`TypedAnnotation::tables` called outside of body")
318+
}
319+
}
320+
321+
impl<'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'tcx> {
313322
fn sess(&self) -> &Session {
314323
&self.tcx.sess
315324
}
@@ -327,15 +336,15 @@ impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> {
327336
}
328337
}
329338

330-
impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> {
339+
impl<'tcx> pprust_hir::PpAnn for TypedAnnotation<'tcx> {
331340
fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
332-
let old_tables = self.tables.get();
341+
let old_maybe_typeck_tables = self.maybe_typeck_tables.get();
333342
if let pprust_hir::Nested::Body(id) = nested {
334-
self.tables.set(self.tcx.body_tables(id));
343+
self.maybe_typeck_tables.set(Some(self.tcx.body_tables(id)));
335344
}
336345
let pp_ann = &(&self.tcx.hir() as &dyn hir::intravisit::Map<'_>);
337346
pprust_hir::PpAnn::nested(pp_ann, state, nested);
338-
self.tables.set(old_tables);
347+
self.maybe_typeck_tables.set(old_maybe_typeck_tables);
339348
}
340349
fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
341350
if let pprust_hir::AnnNode::Expr(_) = node {
@@ -347,7 +356,7 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> {
347356
s.s.space();
348357
s.s.word("as");
349358
s.s.space();
350-
s.s.word(self.tables.get().expr_ty(expr).to_string());
359+
s.s.word(self.tables().expr_ty(expr).to_string());
351360
s.pclose();
352361
}
353362
}

src/librustc_infer/infer/error_reporting/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1684,7 +1684,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16841684
// Attempt to obtain the span of the parameter so we can
16851685
// suggest adding an explicit lifetime bound to it.
16861686
let generics =
1687-
self.in_progress_tables.and_then(|table| table.borrow().hir_owner).map(|table_owner| {
1687+
self.in_progress_tables.map(|table| table.borrow().hir_owner).map(|table_owner| {
16881688
let hir_id = hir.as_local_hir_id(table_owner);
16891689
let parent_id = hir.get_parent_item(hir_id);
16901690
(

src/librustc_infer/infer/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
588588
/// Used only by `rustc_typeck` during body type-checking/inference,
589589
/// will initialize `in_progress_tables` with fresh `TypeckTables`.
590590
pub fn with_fresh_in_progress_tables(mut self, table_owner: LocalDefId) -> Self {
591-
self.fresh_tables = Some(RefCell::new(ty::TypeckTables::empty(Some(table_owner))));
591+
self.fresh_tables = Some(RefCell::new(ty::TypeckTables::new(table_owner)));
592592
self
593593
}
594594

src/librustc_lint/builtin.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns {
165165
.pat_ty(pat)
166166
.ty_adt_def()
167167
.expect("struct pattern type is not an ADT")
168-
.variant_of_res(cx.tables().qpath_res(qpath, pat.hir_id));
168+
.variant_of_res(cx.qpath_res(qpath, pat.hir_id));
169169
for fieldpat in field_pats {
170170
if fieldpat.is_shorthand {
171171
continue;
@@ -901,7 +901,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
901901
expr: &hir::Expr<'_>,
902902
) -> Option<(Ty<'tcx>, Ty<'tcx>)> {
903903
let def = if let hir::ExprKind::Path(ref qpath) = expr.kind {
904-
cx.tables().qpath_res(qpath, expr.hir_id)
904+
cx.qpath_res(qpath, expr.hir_id)
905905
} else {
906906
return None;
907907
};
@@ -1891,7 +1891,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
18911891
if let hir::ExprKind::Call(ref path_expr, ref args) = expr.kind {
18921892
// Find calls to `mem::{uninitialized,zeroed}` methods.
18931893
if let hir::ExprKind::Path(ref qpath) = path_expr.kind {
1894-
let def_id = cx.tables().qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
1894+
let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
18951895

18961896
if cx.tcx.is_diagnostic_item(sym::mem_zeroed, def_id) {
18971897
return Some(InitKind::Zeroed);
@@ -1911,8 +1911,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
19111911
// See if the `self` parameter is one of the dangerous constructors.
19121912
if let hir::ExprKind::Call(ref path_expr, _) = args[0].kind {
19131913
if let hir::ExprKind::Path(ref qpath) = path_expr.kind {
1914-
let def_id =
1915-
cx.tables().qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
1914+
let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
19161915

19171916
if cx.tcx.is_diagnostic_item(sym::maybe_uninit_zeroed, def_id) {
19181917
return Some(InitKind::Zeroed);

src/librustc_lint/context.rs

+28-13
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use rustc_data_structures::fx::FxHashMap;
2424
use rustc_data_structures::sync;
2525
use rustc_errors::{struct_span_err, Applicability};
2626
use rustc_hir as hir;
27+
use rustc_hir::def::Res;
2728
use rustc_hir::def_id::{CrateNum, DefId};
2829
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
2930
use rustc_middle::lint::LintDiagnosticBuilder;
@@ -427,15 +428,12 @@ pub struct LateContext<'a, 'tcx> {
427428
/// Current body, or `None` if outside a body.
428429
pub enclosing_body: Option<hir::BodyId>,
429430

430-
/// Type-checking side-tables for the current body. Access using the
431-
/// `tables` method, which handles querying the tables on demand.
431+
/// Type-checking side-tables for the current body. Access using the `tables`
432+
/// and `maybe_tables` methods, which handle querying the tables on demand.
432433
// FIXME(eddyb) move all the code accessing internal fields like this,
433434
// to this module, to avoid exposing it to lint logic.
434435
pub(super) cached_typeck_tables: Cell<Option<&'tcx ty::TypeckTables<'tcx>>>,
435436

436-
// HACK(eddyb) replace this with having `Option` around `&TypeckTables`.
437-
pub(super) empty_typeck_tables: &'a ty::TypeckTables<'tcx>,
438-
439437
/// Parameter environment for the item we are in.
440438
pub param_env: ty::ParamEnv<'tcx>,
441439

@@ -677,18 +675,35 @@ impl LintContext for EarlyContext<'_> {
677675

678676
impl<'a, 'tcx> LateContext<'a, 'tcx> {
679677
/// Gets the type-checking side-tables for the current body,
680-
/// or empty `TypeckTables` if outside a body.
681-
// FIXME(eddyb) return `Option<&'tcx ty::TypeckTables<'tcx>>`,
682-
// where `None` indicates we're outside a body.
683-
pub fn tables(&self) -> &'a ty::TypeckTables<'tcx> {
684-
if let Some(body) = self.enclosing_body {
685-
self.cached_typeck_tables.get().unwrap_or_else(|| {
678+
/// or `None` if outside a body.
679+
pub fn maybe_typeck_tables(&self) -> Option<&'tcx ty::TypeckTables<'tcx>> {
680+
self.cached_typeck_tables.get().or_else(|| {
681+
self.enclosing_body.map(|body| {
686682
let tables = self.tcx.body_tables(body);
687683
self.cached_typeck_tables.set(Some(tables));
688684
tables
689685
})
690-
} else {
691-
self.empty_typeck_tables
686+
})
687+
}
688+
689+
/// Gets the type-checking side-tables for the current body.
690+
/// As this will ICE if called outside bodies, only call when working with
691+
/// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
692+
#[track_caller]
693+
pub fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> {
694+
self.maybe_typeck_tables().expect("`LateContext::tables` called outside of body")
695+
}
696+
697+
/// Returns the final resolution of a `QPath`, or `Res::Err` if unavailable.
698+
/// Unlike `.tables().qpath_res(qpath, id)`, this can be used even outside
699+
/// bodies (e.g. for paths in `hir::Ty`), without any risk of ICE-ing.
700+
pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
701+
match *qpath {
702+
hir::QPath::Resolved(_, ref path) => path.res,
703+
hir::QPath::TypeRelative(..) => self
704+
.maybe_typeck_tables()
705+
.and_then(|tables| tables.type_dependent_def(id))
706+
.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
692707
}
693708
}
694709

src/librustc_lint/late.rs

-2
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,6 @@ fn late_lint_mod_pass<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(
378378
tcx,
379379
enclosing_body: None,
380380
cached_typeck_tables: Cell::new(None),
381-
empty_typeck_tables: &ty::TypeckTables::empty(None),
382381
param_env: ty::ParamEnv::empty(),
383382
access_levels,
384383
lint_store: unerased_lint_store(tcx),
@@ -427,7 +426,6 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tc
427426
tcx,
428427
enclosing_body: None,
429428
cached_typeck_tables: Cell::new(None),
430-
empty_typeck_tables: &ty::TypeckTables::empty(None),
431429
param_env: ty::ParamEnv::empty(),
432430
access_levels,
433431
lint_store: unerased_lint_store(tcx),

src/librustc_lint/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#![feature(never_type)]
3535
#![feature(nll)]
3636
#![feature(or_patterns)]
37+
#![cfg_attr(bootstrap, feature(track_caller))]
3738
#![recursion_limit = "256"]
3839

3940
#[macro_use]

src/librustc_lint/unused.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
5555
hir::ExprKind::Call(ref callee, _) => {
5656
match callee.kind {
5757
hir::ExprKind::Path(ref qpath) => {
58-
match cx.tables().qpath_res(qpath, callee.hir_id) {
58+
match cx.qpath_res(qpath, callee.hir_id) {
5959
Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => Some(def_id),
6060
// `Res::Local` if it was a closure, for which we
6161
// do not currently support must-use linting

0 commit comments

Comments
 (0)