Skip to content

Commit 547be8c

Browse files
committed
rustc_lint: avoid using TypeckTables::empty for LateContext.
1 parent c034874 commit 547be8c

32 files changed

+104
-90
lines changed

src/librustc_lint/builtin.rs

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

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

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+
#![cfg_attr(bootstrap, feature(track_caller))]
3738
#![recursion_limit = "256"]
3839

3940
#[macro_use]

src/librustc_lint/unused.rs

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

src/tools/clippy/clippy_lints/src/atomic_ordering.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ fn check_atomic_load_store(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
7676
if method == "load" || method == "store";
7777
let ordering_arg = if method == "load" { &args[1] } else { &args[2] };
7878
if let ExprKind::Path(ref ordering_qpath) = ordering_arg.kind;
79-
if let Some(ordering_def_id) = cx.tables().qpath_res(ordering_qpath, ordering_arg.hir_id).opt_def_id();
79+
if let Some(ordering_def_id) = cx.qpath_res(ordering_qpath, ordering_arg.hir_id).opt_def_id();
8080
then {
8181
if method == "load" &&
8282
match_ordering_def_path(cx, ordering_def_id, &["Release", "AcqRel"]) {
@@ -107,12 +107,12 @@ fn check_memory_fence(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
107107
if_chain! {
108108
if let ExprKind::Call(ref func, ref args) = expr.kind;
109109
if let ExprKind::Path(ref func_qpath) = func.kind;
110-
if let Some(def_id) = cx.tables().qpath_res(func_qpath, func.hir_id).opt_def_id();
110+
if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
111111
if ["fence", "compiler_fence"]
112112
.iter()
113113
.any(|func| match_def_path(cx, def_id, &["core", "sync", "atomic", func]));
114114
if let ExprKind::Path(ref ordering_qpath) = &args[0].kind;
115-
if let Some(ordering_def_id) = cx.tables().qpath_res(ordering_qpath, args[0].hir_id).opt_def_id();
115+
if let Some(ordering_def_id) = cx.qpath_res(ordering_qpath, args[0].hir_id).opt_def_id();
116116
if match_ordering_def_path(cx, ordering_def_id, &["Relaxed"]);
117117
then {
118118
span_lint_and_help(

src/tools/clippy/clippy_lints/src/copies.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ fn lint_same_then_else(cx: &LateContext<'_, '_>, blocks: &[&Block<'_>]) {
192192
/// Implementation of `IFS_SAME_COND`.
193193
fn lint_same_cond(cx: &LateContext<'_, '_>, conds: &[&Expr<'_>]) {
194194
let hash: &dyn Fn(&&Expr<'_>) -> u64 = &|expr| -> u64 {
195-
let mut h = SpanlessHash::new(cx, cx.tables());
195+
let mut h = SpanlessHash::new(cx);
196196
h.hash_expr(expr);
197197
h.finish()
198198
};
@@ -215,7 +215,7 @@ fn lint_same_cond(cx: &LateContext<'_, '_>, conds: &[&Expr<'_>]) {
215215
/// Implementation of `SAME_FUNCTIONS_IN_IF_CONDITION`.
216216
fn lint_same_fns_in_if_cond(cx: &LateContext<'_, '_>, conds: &[&Expr<'_>]) {
217217
let hash: &dyn Fn(&&Expr<'_>) -> u64 = &|expr| -> u64 {
218-
let mut h = SpanlessHash::new(cx, cx.tables());
218+
let mut h = SpanlessHash::new(cx);
219219
h.hash_expr(expr);
220220
h.finish()
221221
};
@@ -251,7 +251,7 @@ fn lint_match_arms<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &Expr<'_>) {
251251

252252
if let ExprKind::Match(_, ref arms, MatchSource::Normal) = expr.kind {
253253
let hash = |&(_, arm): &(usize, &Arm<'_>)| -> u64 {
254-
let mut h = SpanlessHash::new(cx, cx.tables());
254+
let mut h = SpanlessHash::new(cx);
255255
h.hash_expr(&arm.body);
256256
h.finish()
257257
};

src/tools/clippy/clippy_lints/src/default_trait_access.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess {
3636
if let ExprKind::Call(ref path, ..) = expr.kind;
3737
if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
3838
if let ExprKind::Path(ref qpath) = path.kind;
39-
if let Some(def_id) = cx.tables().qpath_res(qpath, path.hir_id).opt_def_id();
39+
if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
4040
if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD);
4141
then {
4242
match qpath {

src/tools/clippy/clippy_lints/src/eval_order_dependence.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence {
7575
if let ExprKind::Path(ref qpath) = lhs.kind {
7676
if let QPath::Resolved(_, ref path) = *qpath {
7777
if path.segments.len() == 1 {
78-
if let def::Res::Local(var) = cx.tables().qpath_res(qpath, lhs.hir_id) {
78+
if let def::Res::Local(var) = cx.qpath_res(qpath, lhs.hir_id) {
7979
let mut visitor = ReadVisitor {
8080
cx,
8181
var,
@@ -309,7 +309,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> {
309309
if_chain! {
310310
if let QPath::Resolved(None, ref path) = *qpath;
311311
if path.segments.len() == 1;
312-
if let def::Res::Local(local_id) = self.cx.tables().qpath_res(qpath, expr.hir_id);
312+
if let def::Res::Local(local_id) = self.cx.qpath_res(qpath, expr.hir_id);
313313
if local_id == self.var;
314314
// Check that this is a read, not a write.
315315
if !is_in_assignment_position(self.cx, expr);

src/tools/clippy/clippy_lints/src/format.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ fn on_argumentv1_new<'a, 'tcx>(
8888
// matches `core::fmt::Display::fmt`
8989
if args.len() == 2;
9090
if let ExprKind::Path(ref qpath) = args[1].kind;
91-
if let Some(did) = cx.tables().qpath_res(qpath, args[1].hir_id).opt_def_id();
91+
if let Some(did) = cx.qpath_res(qpath, args[1].hir_id).opt_def_id();
9292
if match_def_path(cx, did, &paths::DISPLAY_FMT_METHOD);
9393
// check `(arg0,)` in match block
9494
if let PatKind::Tuple(ref pats, None) = arms[0].pat.kind;

0 commit comments

Comments
 (0)