Skip to content

Commit 0c5fcce

Browse files
authored
Rollup merge of #81176 - camsteffen:qpath-res, r=oli-obk
Improve safety of `LateContext::qpath_res` This is my first rustc code change, inspired by hacking on clippy! The first change is to clear cached `TypeckResults` from `LateContext` when visiting a nested item. I took a hint from [here](https://github.com/rust-lang/rust/blob/5e91c4ecc09312d8b63d250a432b0f3ef83f1df7/compiler/rustc_privacy/src/lib.rs#L1300). Clippy has a `qpath_res` util function to avoid a possible ICE in `LateContext::qpath_res`. But the docs of `LateContext::qpath_res` promise no ICE. So this updates the `LateContext` method to keep its promises, and removes the util function. Related: rust-lang/rust-clippy#4545 CC ````````````@eddyb```````````` since you've done related work CC ````````````@flip1995```````````` FYI
2 parents 4283623 + eaba3da commit 0c5fcce

16 files changed

+57
-58
lines changed

Diff for: compiler/rustc_lint/src/context.rs

+8
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,14 @@ impl<'tcx> LateContext<'tcx> {
746746
hir::QPath::Resolved(_, ref path) => path.res,
747747
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
748748
.maybe_typeck_results()
749+
.filter(|typeck_results| typeck_results.hir_owner == id.owner)
750+
.or_else(|| {
751+
if self.tcx.has_typeck_results(id.owner.to_def_id()) {
752+
Some(self.tcx.typeck(id.owner))
753+
} else {
754+
None
755+
}
756+
})
749757
.and_then(|typeck_results| typeck_results.type_dependent_def(id))
750758
.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
751759
}

Diff for: compiler/rustc_lint/src/late.rs

+4
Original file line numberDiff line numberDiff line change
@@ -140,13 +140,17 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
140140
fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
141141
let generics = self.context.generics.take();
142142
self.context.generics = it.kind.generics();
143+
let old_cached_typeck_results = self.context.cached_typeck_results.take();
144+
let old_enclosing_body = self.context.enclosing_body.take();
143145
self.with_lint_attrs(it.hir_id, &it.attrs, |cx| {
144146
cx.with_param_env(it.hir_id, |cx| {
145147
lint_callback!(cx, check_item, it);
146148
hir_visit::walk_item(cx, it);
147149
lint_callback!(cx, check_item_post, it);
148150
});
149151
});
152+
self.context.enclosing_body = old_enclosing_body;
153+
self.context.cached_typeck_results.set(old_cached_typeck_results);
150154
self.context.generics = generics;
151155
}
152156

Diff for: src/tools/clippy/clippy_lints/src/default.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::utils::{
2-
any_parent_is_automatically_derived, contains_name, match_def_path, paths, qpath_res, snippet_with_macro_callsite,
2+
any_parent_is_automatically_derived, contains_name, match_def_path, paths, snippet_with_macro_callsite,
33
};
44
use crate::utils::{span_lint_and_note, span_lint_and_sugg};
55
use if_chain::if_chain;
@@ -231,7 +231,7 @@ fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool
231231
if_chain! {
232232
if let ExprKind::Call(ref fn_expr, _) = &expr.kind;
233233
if let ExprKind::Path(qpath) = &fn_expr.kind;
234-
if let Res::Def(_, def_id) = qpath_res(cx, qpath, fn_expr.hir_id);
234+
if let Res::Def(_, def_id) = cx.qpath_res(qpath, fn_expr.hir_id);
235235
then {
236236
// right hand side of assignment is `Default::default`
237237
match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD)

Diff for: src/tools/clippy/clippy_lints/src/drop_forget_ref.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::utils::{is_copy, match_def_path, paths, qpath_res, span_lint_and_note};
1+
use crate::utils::{is_copy, match_def_path, paths, span_lint_and_note};
22
use if_chain::if_chain;
33
use rustc_hir::{Expr, ExprKind};
44
use rustc_lint::{LateContext, LateLintPass};
@@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
114114
if let ExprKind::Call(ref path, ref args) = expr.kind;
115115
if let ExprKind::Path(ref qpath) = path.kind;
116116
if args.len() == 1;
117-
if let Some(def_id) = qpath_res(cx, qpath, path.hir_id).opt_def_id();
117+
if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
118118
then {
119119
let lint;
120120
let msg;

Diff for: src/tools/clippy/clippy_lints/src/exit.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::utils::{is_entrypoint_fn, match_def_path, paths, qpath_res, span_lint};
1+
use crate::utils::{is_entrypoint_fn, match_def_path, paths, span_lint};
22
use if_chain::if_chain;
33
use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node};
44
use rustc_lint::{LateContext, LateLintPass};
@@ -29,7 +29,7 @@ impl<'tcx> LateLintPass<'tcx> for Exit {
2929
if_chain! {
3030
if let ExprKind::Call(ref path_expr, ref _args) = e.kind;
3131
if let ExprKind::Path(ref path) = path_expr.kind;
32-
if let Some(def_id) = qpath_res(cx, path, path_expr.hir_id).opt_def_id();
32+
if let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id();
3333
if match_def_path(cx, def_id, &paths::EXIT);
3434
then {
3535
let parent = cx.tcx.hir().get_parent_item(e.hir_id);

Diff for: src/tools/clippy/clippy_lints/src/functions.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::utils::{
22
attr_by_name, attrs::is_proc_macro, is_must_use_ty, is_trait_impl_item, is_type_diagnostic_item, iter_input_pats,
3-
last_path_segment, match_def_path, must_use_attr, qpath_res, return_ty, snippet, snippet_opt, span_lint,
4-
span_lint_and_help, span_lint_and_then, trait_ref_of_method, type_is_unsafe_function,
3+
last_path_segment, match_def_path, must_use_attr, return_ty, snippet, snippet_opt, span_lint, span_lint_and_help,
4+
span_lint_and_then, trait_ref_of_method, type_is_unsafe_function,
55
};
66
use if_chain::if_chain;
77
use rustc_ast::ast::Attribute;
@@ -659,7 +659,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
659659
impl<'a, 'tcx> DerefVisitor<'a, 'tcx> {
660660
fn check_arg(&self, ptr: &hir::Expr<'_>) {
661661
if let hir::ExprKind::Path(ref qpath) = ptr.kind {
662-
if let Res::Local(id) = qpath_res(self.cx, qpath, ptr.hir_id) {
662+
if let Res::Local(id) = self.cx.qpath_res(qpath, ptr.hir_id) {
663663
if self.ptrs.contains(&id) {
664664
span_lint(
665665
self.cx,
@@ -722,7 +722,7 @@ fn is_mutated_static(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> bool {
722722
use hir::ExprKind::{Field, Index, Path};
723723

724724
match e.kind {
725-
Path(ref qpath) => !matches!(qpath_res(cx, qpath, e.hir_id), Res::Local(_)),
725+
Path(ref qpath) => !matches!(cx.qpath_res(qpath, e.hir_id), Res::Local(_)),
726726
Field(ref inner, _) | Index(ref inner, _) => is_mutated_static(cx, inner),
727727
_ => false,
728728
}

Diff for: src/tools/clippy/clippy_lints/src/let_if_seq.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::utils::{qpath_res, snippet, span_lint_and_then, visitors::LocalUsedVisitor};
1+
use crate::utils::{snippet, span_lint_and_then, visitors::LocalUsedVisitor};
22
use if_chain::if_chain;
33
use rustc_errors::Applicability;
44
use rustc_hir as hir;
@@ -145,7 +145,7 @@ fn check_assign<'tcx>(
145145
if let hir::StmtKind::Semi(ref expr) = expr.kind;
146146
if let hir::ExprKind::Assign(ref var, ref value, _) = expr.kind;
147147
if let hir::ExprKind::Path(ref qpath) = var.kind;
148-
if let Res::Local(local_id) = qpath_res(cx, qpath, var.hir_id);
148+
if let Res::Local(local_id) = cx.qpath_res(qpath, var.hir_id);
149149
if decl == local_id;
150150
then {
151151
let mut v = LocalUsedVisitor::new(decl);

Diff for: src/tools/clippy/clippy_lints/src/loops.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ use crate::utils::visitors::LocalUsedVisitor;
66
use crate::utils::{
77
contains_name, get_enclosing_block, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait,
88
indent_of, is_in_panic_handler, is_integer_const, is_no_std_crate, is_refutable, is_type_diagnostic_item,
9-
last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, qpath_res, single_segment_path,
10-
snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help,
11-
span_lint_and_sugg, span_lint_and_then, sugg, SpanlessEq,
9+
last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, single_segment_path, snippet,
10+
snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg,
11+
span_lint_and_then, sugg, SpanlessEq,
1212
};
1313
use if_chain::if_chain;
1414
use rustc_ast::ast;
@@ -848,7 +848,7 @@ fn same_var<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, var: HirId) -> bool {
848848
if let ExprKind::Path(qpath) = &expr.kind;
849849
if let QPath::Resolved(None, path) = qpath;
850850
if path.segments.len() == 1;
851-
if let Res::Local(local_id) = qpath_res(cx, qpath, expr.hir_id);
851+
if let Res::Local(local_id) = cx.qpath_res(qpath, expr.hir_id);
852852
then {
853853
// our variable!
854854
local_id == var
@@ -1420,7 +1420,7 @@ fn detect_same_item_push<'tcx>(
14201420
// Make sure that the push does not involve possibly mutating values
14211421
match pushed_item.kind {
14221422
ExprKind::Path(ref qpath) => {
1423-
match qpath_res(cx, qpath, pushed_item.hir_id) {
1423+
match cx.qpath_res(qpath, pushed_item.hir_id) {
14241424
// immutable bindings that are initialized with literal or constant
14251425
Res::Local(hir_id) => {
14261426
if_chain! {
@@ -1437,7 +1437,7 @@ fn detect_same_item_push<'tcx>(
14371437
ExprKind::Lit(..) => emit_lint(cx, vec, pushed_item),
14381438
// immutable bindings that are initialized with constant
14391439
ExprKind::Path(ref path) => {
1440-
if let Res::Def(DefKind::Const, ..) = qpath_res(cx, path, init.hir_id) {
1440+
if let Res::Def(DefKind::Const, ..) = cx.qpath_res(path, init.hir_id) {
14411441
emit_lint(cx, vec, pushed_item);
14421442
}
14431443
}
@@ -2028,7 +2028,7 @@ fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option<HirId>
20282028
if let ExprKind::Path(ref qpath) = bound.kind;
20292029
if let QPath::Resolved(None, _) = *qpath;
20302030
then {
2031-
let res = qpath_res(cx, qpath, bound.hir_id);
2031+
let res = cx.qpath_res(qpath, bound.hir_id);
20322032
if let Res::Local(hir_id) = res {
20332033
let node_str = cx.tcx.hir().get(hir_id);
20342034
if_chain! {
@@ -2120,7 +2120,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
21202120
if self.prefer_mutable {
21212121
self.indexed_mut.insert(seqvar.segments[0].ident.name);
21222122
}
2123-
let res = qpath_res(self.cx, seqpath, seqexpr.hir_id);
2123+
let res = self.cx.qpath_res(seqpath, seqexpr.hir_id);
21242124
match res {
21252125
Res::Local(hir_id) => {
21262126
let parent_id = self.cx.tcx.hir().get_parent_item(expr.hir_id);
@@ -2184,7 +2184,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
21842184
if let QPath::Resolved(None, ref path) = *qpath;
21852185
if path.segments.len() == 1;
21862186
then {
2187-
if let Res::Local(local_id) = qpath_res(self.cx, qpath, expr.hir_id) {
2187+
if let Res::Local(local_id) = self.cx.qpath_res(qpath, expr.hir_id) {
21882188
if local_id == self.var {
21892189
self.nonindex = true;
21902190
} else {
@@ -2589,7 +2589,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
25892589

25902590
fn var_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<HirId> {
25912591
if let ExprKind::Path(ref qpath) = expr.kind {
2592-
let path_res = qpath_res(cx, qpath, expr.hir_id);
2592+
let path_res = cx.qpath_res(qpath, expr.hir_id);
25932593
if let Res::Local(hir_id) = path_res {
25942594
return Some(hir_id);
25952595
}
@@ -2819,7 +2819,7 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> {
28192819
if_chain! {
28202820
if let ExprKind::Path(ref qpath) = ex.kind;
28212821
if let QPath::Resolved(None, _) = *qpath;
2822-
let res = qpath_res(self.cx, qpath, ex.hir_id);
2822+
let res = self.cx.qpath_res(qpath, ex.hir_id);
28232823
then {
28242824
match res {
28252825
Res::Local(hir_id) => {

Diff for: src/tools/clippy/clippy_lints/src/manual_strip.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::consts::{constant, Constant};
22
use crate::utils::usage::mutated_variables;
33
use crate::utils::{
4-
eq_expr_value, higher, match_def_path, meets_msrv, multispan_sugg, paths, qpath_res, snippet, span_lint_and_then,
4+
eq_expr_value, higher, match_def_path, meets_msrv, multispan_sugg, paths, snippet, span_lint_and_then,
55
};
66

77
use if_chain::if_chain;
@@ -92,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
9292
} else {
9393
return;
9494
};
95-
let target_res = qpath_res(cx, &target_path, target_arg.hir_id);
95+
let target_res = cx.qpath_res(&target_path, target_arg.hir_id);
9696
if target_res == Res::Err {
9797
return;
9898
};
@@ -221,7 +221,7 @@ fn find_stripping<'tcx>(
221221
if let ExprKind::Index(indexed, index) = &unref.kind;
222222
if let Some(higher::Range { start, end, .. }) = higher::range(index);
223223
if let ExprKind::Path(path) = &indexed.kind;
224-
if qpath_res(self.cx, path, ex.hir_id) == self.target;
224+
if self.cx.qpath_res(path, ex.hir_id) == self.target;
225225
then {
226226
match (self.strip_kind, start, end) {
227227
(StripKind::Prefix, Some(start), None) => {
@@ -235,7 +235,7 @@ fn find_stripping<'tcx>(
235235
if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, left, right) = end.kind;
236236
if let Some(left_arg) = len_arg(self.cx, left);
237237
if let ExprKind::Path(left_path) = &left_arg.kind;
238-
if qpath_res(self.cx, left_path, left_arg.hir_id) == self.target;
238+
if self.cx.qpath_res(left_path, left_arg.hir_id) == self.target;
239239
if eq_pattern_length(self.cx, self.pattern, right);
240240
then {
241241
self.results.push(ex.span);

Diff for: src/tools/clippy/clippy_lints/src/mem_forget.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::utils::{match_def_path, paths, qpath_res, span_lint};
1+
use crate::utils::{match_def_path, paths, span_lint};
22
use rustc_hir::{Expr, ExprKind};
33
use rustc_lint::{LateContext, LateLintPass};
44
use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -29,7 +29,7 @@ impl<'tcx> LateLintPass<'tcx> for MemForget {
2929
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
3030
if let ExprKind::Call(ref path_expr, ref args) = e.kind {
3131
if let ExprKind::Path(ref qpath) = path_expr.kind {
32-
if let Some(def_id) = qpath_res(cx, qpath, path_expr.hir_id).opt_def_id() {
32+
if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id() {
3333
if match_def_path(cx, def_id, &paths::MEM_FORGET) {
3434
let forgot_ty = cx.typeck_results().expr_ty(&args[0]);
3535

Diff for: src/tools/clippy/clippy_lints/src/no_effect.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::utils::{has_drop, qpath_res, snippet_opt, span_lint, span_lint_and_sugg};
1+
use crate::utils::{has_drop, snippet_opt, span_lint, span_lint_and_sugg};
22
use rustc_errors::Applicability;
33
use rustc_hir::def::{DefKind, Res};
44
use rustc_hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource};
@@ -67,7 +67,7 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
6767
},
6868
ExprKind::Call(ref callee, ref args) => {
6969
if let ExprKind::Path(ref qpath) = callee.kind {
70-
let res = qpath_res(cx, qpath, callee.hir_id);
70+
let res = cx.qpath_res(qpath, callee.hir_id);
7171
match res {
7272
Res::Def(DefKind::Struct | DefKind::Variant | DefKind::Ctor(..), ..) => {
7373
!has_drop(cx, cx.typeck_results().expr_ty(expr))
@@ -146,7 +146,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec
146146
},
147147
ExprKind::Call(ref callee, ref args) => {
148148
if let ExprKind::Path(ref qpath) = callee.kind {
149-
let res = qpath_res(cx, qpath, callee.hir_id);
149+
let res = cx.qpath_res(qpath, callee.hir_id);
150150
match res {
151151
Res::Def(DefKind::Struct | DefKind::Variant | DefKind::Ctor(..), ..)
152152
if !has_drop(cx, cx.typeck_results().expr_ty(expr)) =>

Diff for: src/tools/clippy/clippy_lints/src/non_copy_const.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
1818
use rustc_span::{InnerSpan, Span, DUMMY_SP};
1919
use rustc_typeck::hir_ty_to_ty;
2020

21-
use crate::utils::{in_constant, qpath_res, span_lint_and_then};
21+
use crate::utils::{in_constant, span_lint_and_then};
2222
use if_chain::if_chain;
2323

2424
// FIXME: this is a correctness problem but there's no suitable
@@ -339,7 +339,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
339339
}
340340

341341
// Make sure it is a const item.
342-
let item_def_id = match qpath_res(cx, qpath, expr.hir_id) {
342+
let item_def_id = match cx.qpath_res(qpath, expr.hir_id) {
343343
Res::Def(DefKind::Const | DefKind::AssocConst, did) => did,
344344
_ => return,
345345
};

Diff for: src/tools/clippy/clippy_lints/src/to_string_in_display.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::utils::{match_def_path, match_trait_method, paths, qpath_res, span_lint};
1+
use crate::utils::{match_def_path, match_trait_method, paths, span_lint};
22
use if_chain::if_chain;
33
use rustc_hir::def::Res;
44
use rustc_hir::{Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind};
@@ -94,7 +94,7 @@ impl LateLintPass<'_> for ToStringInDisplay {
9494
if match_trait_method(cx, expr, &paths::TO_STRING);
9595
if self.in_display_impl;
9696
if let ExprKind::Path(ref qpath) = args[0].kind;
97-
if let Res::Local(hir_id) = qpath_res(cx, qpath, args[0].hir_id);
97+
if let Res::Local(hir_id) = cx.qpath_res(qpath, args[0].hir_id);
9898
if let Some(self_hir_id) = self.self_hir_id;
9999
if hir_id == self_hir_id;
100100
then {

0 commit comments

Comments
 (0)