Skip to content

Commit db59d2a

Browse files
authored
Fix ICE when the clippy::author attribute is applied to an item (#17245)
changelog: [`author`]: attribute can be applied to items Fixes #17240 r? Jarcho
2 parents b6eda57 + 15025dc commit db59d2a

3 files changed

Lines changed: 54 additions & 8 deletions

File tree

clippy_lints/src/utils/author.rs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ use rustc_ast::ast::{LitFloatType, LitKind};
66
use rustc_data_structures::fx::FxHashMap;
77
use rustc_hir::def_id::DefId;
88
use rustc_hir::{
9-
self as hir, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind, ExprKind,
9+
self as hir, BindingMode, Body, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind, ExprKind,
1010
FnRetTy, HirId, Lit, PatExprKind, PatKind, QPath, StmtKind, StructTailExpr,
1111
};
1212
use rustc_lint::{LateContext, LateLintPass};
13-
use rustc_middle::ty::{FloatTy, IntTy, UintTy};
13+
use rustc_middle::ty::{FloatTy, IntTy, TypeckResults, UintTy};
1414
use rustc_session::declare_lint_pass;
1515
use rustc_span::symbol::{Ident, Symbol};
1616
use std::cell::Cell;
@@ -137,15 +137,31 @@ impl<'tcx> LateLintPass<'tcx> for Author {
137137

138138
fn check_item(cx: &LateContext<'_>, hir_id: HirId) {
139139
if let Some(body) = cx.tcx.hir_maybe_body_owned_by(hir_id.expect_owner().def_id) {
140-
check_node(cx, hir_id, |v| {
141-
v.expr(&v.bind("expr", body.value));
142-
});
140+
check_node_with_body(
141+
cx,
142+
hir_id,
143+
|v| {
144+
v.expr(&v.bind("expr", body.value));
145+
},
146+
Some(body),
147+
);
143148
}
144149
}
145150

146151
fn check_node(cx: &LateContext<'_>, hir_id: HirId, f: impl Fn(&PrintVisitor<'_, '_>)) {
152+
check_node_with_body(cx, hir_id, f, None);
153+
}
154+
155+
/// Check the node at `hir_id`, in the context of `body` or the default from `cx` if none is given.
156+
fn check_node_with_body(
157+
cx: &LateContext<'_>,
158+
hir_id: HirId,
159+
f: impl Fn(&PrintVisitor<'_, '_>),
160+
body: Option<&Body<'_>>,
161+
) {
147162
if has_attr(cx, hir_id) {
148-
f(&PrintVisitor::new(cx));
163+
let typeck_results = body.map_or_else(|| cx.typeck_results(), |body| cx.tcx.typeck_body(body.id()));
164+
f(&PrintVisitor::new(cx, typeck_results));
149165
println!("{{");
150166
println!(" // report your lint here");
151167
println!("}}");
@@ -199,6 +215,7 @@ impl<T: Display> Display for OptionPat<T> {
199215

200216
struct PrintVisitor<'a, 'tcx> {
201217
cx: &'a LateContext<'tcx>,
218+
typeck_results: &'tcx TypeckResults<'tcx>,
202219
/// Fields are the current index that needs to be appended to pattern
203220
/// binding names
204221
ids: Cell<FxHashMap<&'static str, u32>>,
@@ -207,9 +224,10 @@ struct PrintVisitor<'a, 'tcx> {
207224
}
208225

209226
impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
210-
fn new(cx: &'a LateContext<'tcx>) -> Self {
227+
fn new(cx: &'a LateContext<'tcx>, typeck_results: &'tcx TypeckResults<'tcx>) -> Self {
211228
Self {
212229
cx,
230+
typeck_results,
213231
ids: Cell::default(),
214232
first: Cell::new(true),
215233
}
@@ -291,7 +309,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
291309
}
292310

293311
fn maybe_path<'p>(&self, path: &Binding<impl MaybeQPath<'p>>) {
294-
if let Some(id) = path.value.res(self.cx).opt_def_id()
312+
if let Some(id) = path.value.res(self.typeck_results).opt_def_id()
295313
&& !id.is_local()
296314
{
297315
if let Some(lang) = self.cx.tcx.lang_items().from_def_id(id) {

tests/ui/author/issue_17240.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//@ check-pass
2+
// Ensure that a proper body is used when printing paths (`x`)
3+
// if the attribute is placed on an item.
4+
#[clippy::author]
5+
fn main() {
6+
let x = 42i32;
7+
_ = -x;
8+
}

tests/ui/author/issue_17240.stdout

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
if let ExprKind::Block(block, None) = expr.kind
2+
&& block.stmts.len() == 2
3+
&& let StmtKind::Let(local) = block.stmts[0].kind
4+
&& let Some(init) = local.init
5+
&& let ExprKind::Lit(ref lit) = init.kind
6+
&& let LitKind::Int(42, LitIntType::Signed(IntTy::I32)) = lit.node
7+
&& let PatKind::Binding(BindingMode::NONE, _, name, None) = local.pat.kind
8+
&& name.as_str() == "x"
9+
&& let StmtKind::Semi(e) = block.stmts[1].kind
10+
&& let ExprKind::Block(block1, None) = e.kind
11+
&& block1.stmts.len() == 1
12+
&& let StmtKind::Let(local1) = block1.stmts[0].kind
13+
&& let Some(init1) = local1.init
14+
&& let ExprKind::Unary(UnOp::Neg, inner) = init1.kind
15+
&& let PatKind::Wild = local1.pat.kind
16+
&& block1.expr.is_none()
17+
&& block.expr.is_none()
18+
{
19+
// report your lint here
20+
}

0 commit comments

Comments
 (0)