Skip to content

Commit c1e62c7

Browse files
authored
Rollup merge of rust-lang#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 e7ec561 + 4118090 commit c1e62c7

File tree

19 files changed

+271
-301
lines changed

19 files changed

+271
-301
lines changed

src/librustc_driver/lib.rs

Lines changed: 1 addition & 0 deletions
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+
#![feature(track_caller)]
910
#![recursion_limit = "256"]
1011

1112
#[macro_use]

src/librustc_driver/pretty.rs

Lines changed: 19 additions & 10 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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/context.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -427,15 +427,12 @@ pub struct LateContext<'a, 'tcx> {
427427
/// Current body, or `None` if outside a body.
428428
pub enclosing_body: Option<hir::BodyId>,
429429

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

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

@@ -677,19 +674,23 @@ impl LintContext for EarlyContext<'_> {
677674

678675
impl<'a, 'tcx> LateContext<'a, 'tcx> {
679676
/// 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(|| {
677+
/// or `None` if outside a body.
678+
pub fn maybe_tables(&self) -> Option<&'tcx ty::TypeckTables<'tcx>> {
679+
self.cached_typeck_tables.get().or_else(|| {
680+
self.enclosing_body.map(|body| {
686681
let tables = self.tcx.body_tables(body);
687682
self.cached_typeck_tables.set(Some(tables));
688683
tables
689684
})
690-
} else {
691-
self.empty_typeck_tables
692-
}
685+
})
686+
}
687+
688+
/// Gets the type-checking side-tables for the current body.
689+
/// As this will ICE if called outside bodies, only call when working with
690+
/// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
691+
#[track_caller]
692+
pub fn tables(&self) -> &'tcx ty::TypeckTables<'tcx> {
693+
self.maybe_tables().expect("`LateContext::tables` called outside of body")
693694
}
694695

695696
pub fn current_lint_root(&self) -> hir::HirId {

src/librustc_lint/late.rs

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#![feature(never_type)]
3535
#![feature(nll)]
3636
#![feature(or_patterns)]
37+
#![feature(track_caller)]
3738
#![recursion_limit = "256"]
3839

3940
#[macro_use]

src/librustc_middle/ty/context.rs

Lines changed: 27 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ pub struct CommonConsts<'tcx> {
188188
}
189189

190190
pub struct LocalTableInContext<'a, V> {
191-
hir_owner: Option<LocalDefId>,
191+
hir_owner: LocalDefId,
192192
data: &'a ItemLocalMap<V>,
193193
}
194194

@@ -199,42 +199,27 @@ pub struct LocalTableInContext<'a, V> {
199199
/// would be in a different frame of reference and using its `local_id`
200200
/// would result in lookup errors, or worse, in silently wrong data being
201201
/// stored/returned.
202-
fn validate_hir_id_for_typeck_tables(
203-
hir_owner: Option<LocalDefId>,
204-
hir_id: hir::HirId,
205-
mut_access: bool,
206-
) {
207-
if let Some(hir_owner) = hir_owner {
208-
if hir_id.owner != hir_owner {
209-
ty::tls::with(|tcx| {
210-
bug!(
211-
"node {} with HirId::owner {:?} cannot be placed in TypeckTables with hir_owner {:?}",
212-
tcx.hir().node_to_string(hir_id),
213-
hir_id.owner,
214-
hir_owner
215-
)
216-
});
217-
}
218-
} else {
219-
// We use "Null Object" TypeckTables in some of the analysis passes.
220-
// These are just expected to be empty and their `hir_owner` is
221-
// `None`. Therefore we cannot verify whether a given `HirId` would
222-
// be a valid key for the given table. Instead we make sure that
223-
// nobody tries to write to such a Null Object table.
224-
if mut_access {
225-
bug!("access to invalid TypeckTables")
226-
}
202+
fn validate_hir_id_for_typeck_tables(hir_owner: LocalDefId, hir_id: hir::HirId) {
203+
if hir_id.owner != hir_owner {
204+
ty::tls::with(|tcx| {
205+
bug!(
206+
"node {} with HirId::owner {:?} cannot be placed in TypeckTables with hir_owner {:?}",
207+
tcx.hir().node_to_string(hir_id),
208+
hir_id.owner,
209+
hir_owner
210+
)
211+
});
227212
}
228213
}
229214

230215
impl<'a, V> LocalTableInContext<'a, V> {
231216
pub fn contains_key(&self, id: hir::HirId) -> bool {
232-
validate_hir_id_for_typeck_tables(self.hir_owner, id, false);
217+
validate_hir_id_for_typeck_tables(self.hir_owner, id);
233218
self.data.contains_key(&id.local_id)
234219
}
235220

236221
pub fn get(&self, id: hir::HirId) -> Option<&V> {
237-
validate_hir_id_for_typeck_tables(self.hir_owner, id, false);
222+
validate_hir_id_for_typeck_tables(self.hir_owner, id);
238223
self.data.get(&id.local_id)
239224
}
240225

@@ -252,28 +237,28 @@ impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
252237
}
253238

254239
pub struct LocalTableInContextMut<'a, V> {
255-
hir_owner: Option<LocalDefId>,
240+
hir_owner: LocalDefId,
256241
data: &'a mut ItemLocalMap<V>,
257242
}
258243

259244
impl<'a, V> LocalTableInContextMut<'a, V> {
260245
pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> {
261-
validate_hir_id_for_typeck_tables(self.hir_owner, id, true);
246+
validate_hir_id_for_typeck_tables(self.hir_owner, id);
262247
self.data.get_mut(&id.local_id)
263248
}
264249

265250
pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> {
266-
validate_hir_id_for_typeck_tables(self.hir_owner, id, true);
251+
validate_hir_id_for_typeck_tables(self.hir_owner, id);
267252
self.data.entry(id.local_id)
268253
}
269254

270255
pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> {
271-
validate_hir_id_for_typeck_tables(self.hir_owner, id, true);
256+
validate_hir_id_for_typeck_tables(self.hir_owner, id);
272257
self.data.insert(id.local_id, val)
273258
}
274259

275260
pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
276-
validate_hir_id_for_typeck_tables(self.hir_owner, id, true);
261+
validate_hir_id_for_typeck_tables(self.hir_owner, id);
277262
self.data.remove(&id.local_id)
278263
}
279264
}
@@ -324,7 +309,7 @@ pub struct GeneratorInteriorTypeCause<'tcx> {
324309
#[derive(RustcEncodable, RustcDecodable, Debug)]
325310
pub struct TypeckTables<'tcx> {
326311
/// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
327-
pub hir_owner: Option<LocalDefId>,
312+
pub hir_owner: LocalDefId,
328313

329314
/// Resolved definitions for `<T>::X` associated paths and
330315
/// method calls, including those of overloaded operators.
@@ -432,7 +417,7 @@ pub struct TypeckTables<'tcx> {
432417
}
433418

434419
impl<'tcx> TypeckTables<'tcx> {
435-
pub fn empty(hir_owner: Option<LocalDefId>) -> TypeckTables<'tcx> {
420+
pub fn new(hir_owner: LocalDefId) -> TypeckTables<'tcx> {
436421
TypeckTables {
437422
hir_owner,
438423
type_dependent_defs: Default::default(),
@@ -474,7 +459,7 @@ impl<'tcx> TypeckTables<'tcx> {
474459
}
475460

476461
pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
477-
validate_hir_id_for_typeck_tables(self.hir_owner, id, false);
462+
validate_hir_id_for_typeck_tables(self.hir_owner, id);
478463
self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
479464
}
480465

@@ -521,7 +506,7 @@ impl<'tcx> TypeckTables<'tcx> {
521506
}
522507

523508
pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
524-
validate_hir_id_for_typeck_tables(self.hir_owner, id, false);
509+
validate_hir_id_for_typeck_tables(self.hir_owner, id);
525510
self.node_types.get(&id.local_id).cloned()
526511
}
527512

@@ -530,12 +515,12 @@ impl<'tcx> TypeckTables<'tcx> {
530515
}
531516

532517
pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
533-
validate_hir_id_for_typeck_tables(self.hir_owner, id, false);
518+
validate_hir_id_for_typeck_tables(self.hir_owner, id);
534519
self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
535520
}
536521

537522
pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
538-
validate_hir_id_for_typeck_tables(self.hir_owner, id, false);
523+
validate_hir_id_for_typeck_tables(self.hir_owner, id);
539524
self.node_substs.get(&id.local_id).cloned()
540525
}
541526

@@ -578,7 +563,7 @@ impl<'tcx> TypeckTables<'tcx> {
578563
}
579564

580565
pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
581-
validate_hir_id_for_typeck_tables(self.hir_owner, expr.hir_id, false);
566+
validate_hir_id_for_typeck_tables(self.hir_owner, expr.hir_id);
582567
self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
583568
}
584569

@@ -657,7 +642,7 @@ impl<'tcx> TypeckTables<'tcx> {
657642
}
658643

659644
pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
660-
validate_hir_id_for_typeck_tables(self.hir_owner, hir_id, true);
645+
validate_hir_id_for_typeck_tables(self.hir_owner, hir_id);
661646
self.coercion_casts.contains(&hir_id.local_id)
662647
}
663648

@@ -710,7 +695,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckTables<'tcx> {
710695
hash_stable_hashmap(hcx, hasher, upvar_capture_map, |up_var_id, hcx| {
711696
let ty::UpvarId { var_path, closure_expr_id } = *up_var_id;
712697

713-
assert_eq!(Some(var_path.hir_id.owner), hir_owner);
698+
assert_eq!(var_path.hir_id.owner, hir_owner);
714699

715700
(
716701
hcx.local_def_path_hash(var_path.hir_id.owner),

0 commit comments

Comments
 (0)