Normalize type aliases when checking significant drops.
This commit is contained in:
parent
0ea88b90d8
commit
75e1d72093
@ -1,7 +1,7 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::source::{indent_of, snippet};
|
use clippy_utils::source::{indent_of, snippet};
|
||||||
use clippy_utils::{expr_or_init, get_attr, path_to_local, peel_hir_expr_unary};
|
use clippy_utils::{expr_or_init, get_attr, path_to_local, peel_hir_expr_unary};
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::intravisit::{walk_expr, Visitor};
|
use rustc_hir::intravisit::{walk_expr, Visitor};
|
||||||
@ -12,6 +12,7 @@ use rustc_session::impl_lint_pass;
|
|||||||
use rustc_span::symbol::Ident;
|
use rustc_span::symbol::Ident;
|
||||||
use rustc_span::{sym, Span, DUMMY_SP};
|
use rustc_span::{sym, Span, DUMMY_SP};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use std::collections::hash_map::Entry;
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
@ -57,7 +58,6 @@ impl_lint_pass!(SignificantDropTightening<'_> => [SIGNIFICANT_DROP_TIGHTENING]);
|
|||||||
pub struct SignificantDropTightening<'tcx> {
|
pub struct SignificantDropTightening<'tcx> {
|
||||||
apas: FxIndexMap<HirId, AuxParamsAttr>,
|
apas: FxIndexMap<HirId, AuxParamsAttr>,
|
||||||
/// Auxiliary structure used to avoid having to verify the same type multiple times.
|
/// Auxiliary structure used to avoid having to verify the same type multiple times.
|
||||||
seen_types: FxHashSet<Ty<'tcx>>,
|
|
||||||
type_cache: FxHashMap<Ty<'tcx>, bool>,
|
type_cache: FxHashMap<Ty<'tcx>, bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
|
|||||||
self.apas.clear();
|
self.apas.clear();
|
||||||
let initial_dummy_stmt = dummy_stmt_expr(body.value);
|
let initial_dummy_stmt = dummy_stmt_expr(body.value);
|
||||||
let mut ap = AuxParams::new(&mut self.apas, &initial_dummy_stmt);
|
let mut ap = AuxParams::new(&mut self.apas, &initial_dummy_stmt);
|
||||||
StmtsChecker::new(&mut ap, cx, &mut self.seen_types, &mut self.type_cache).visit_body(body);
|
StmtsChecker::new(&mut ap, cx, &mut self.type_cache).visit_body(body);
|
||||||
for apa in ap.apas.values() {
|
for apa in ap.apas.values() {
|
||||||
if apa.counter <= 1 || !apa.has_expensive_expr_after_last_attr {
|
if apa.counter <= 1 || !apa.has_expensive_expr_after_last_attr {
|
||||||
continue;
|
continue;
|
||||||
@ -142,28 +142,25 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
|
|||||||
/// Checks the existence of the `#[has_significant_drop]` attribute.
|
/// Checks the existence of the `#[has_significant_drop]` attribute.
|
||||||
struct AttrChecker<'cx, 'others, 'tcx> {
|
struct AttrChecker<'cx, 'others, 'tcx> {
|
||||||
cx: &'cx LateContext<'tcx>,
|
cx: &'cx LateContext<'tcx>,
|
||||||
seen_types: &'others mut FxHashSet<Ty<'tcx>>,
|
|
||||||
type_cache: &'others mut FxHashMap<Ty<'tcx>, bool>,
|
type_cache: &'others mut FxHashMap<Ty<'tcx>, bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
|
impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(cx: &'cx LateContext<'tcx>, type_cache: &'others mut FxHashMap<Ty<'tcx>, bool>) -> Self {
|
||||||
cx: &'cx LateContext<'tcx>,
|
Self { cx, type_cache }
|
||||||
seen_types: &'others mut FxHashSet<Ty<'tcx>>,
|
|
||||||
type_cache: &'others mut FxHashMap<Ty<'tcx>, bool>,
|
|
||||||
) -> Self {
|
|
||||||
seen_types.clear();
|
|
||||||
Self {
|
|
||||||
cx,
|
|
||||||
seen_types,
|
|
||||||
type_cache,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool {
|
fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool {
|
||||||
// The borrow checker prevents us from using something fancier like or_insert_with.
|
let ty = self
|
||||||
if let Some(ty) = self.type_cache.get(&ty) {
|
.cx
|
||||||
return *ty;
|
.tcx
|
||||||
|
.try_normalize_erasing_regions(self.cx.param_env, ty)
|
||||||
|
.unwrap_or(ty);
|
||||||
|
match self.type_cache.entry(ty) {
|
||||||
|
Entry::Occupied(e) => return *e.get(),
|
||||||
|
Entry::Vacant(e) => {
|
||||||
|
e.insert(false);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
let value = self.has_sig_drop_attr_uncached(ty);
|
let value = self.has_sig_drop_attr_uncached(ty);
|
||||||
self.type_cache.insert(ty, value);
|
self.type_cache.insert(ty, value);
|
||||||
@ -185,7 +182,7 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
|
|||||||
rustc_middle::ty::Adt(a, b) => {
|
rustc_middle::ty::Adt(a, b) => {
|
||||||
for f in a.all_fields() {
|
for f in a.all_fields() {
|
||||||
let ty = f.ty(self.cx.tcx, b);
|
let ty = f.ty(self.cx.tcx, b);
|
||||||
if !self.has_seen_ty(ty) && self.has_sig_drop_attr(ty) {
|
if self.has_sig_drop_attr(ty) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -205,16 +202,11 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
|
|||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_seen_ty(&mut self, ty: Ty<'tcx>) -> bool {
|
|
||||||
!self.seen_types.insert(ty)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx> {
|
struct StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx> {
|
||||||
ap: &'ap mut AuxParams<'others, 'stmt, 'tcx>,
|
ap: &'ap mut AuxParams<'others, 'stmt, 'tcx>,
|
||||||
cx: &'lc LateContext<'tcx>,
|
cx: &'lc LateContext<'tcx>,
|
||||||
seen_types: &'others mut FxHashSet<Ty<'tcx>>,
|
|
||||||
type_cache: &'others mut FxHashMap<Ty<'tcx>, bool>,
|
type_cache: &'others mut FxHashMap<Ty<'tcx>, bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,15 +214,9 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx
|
|||||||
fn new(
|
fn new(
|
||||||
ap: &'ap mut AuxParams<'others, 'stmt, 'tcx>,
|
ap: &'ap mut AuxParams<'others, 'stmt, 'tcx>,
|
||||||
cx: &'lc LateContext<'tcx>,
|
cx: &'lc LateContext<'tcx>,
|
||||||
seen_types: &'others mut FxHashSet<Ty<'tcx>>,
|
|
||||||
type_cache: &'others mut FxHashMap<Ty<'tcx>, bool>,
|
type_cache: &'others mut FxHashMap<Ty<'tcx>, bool>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self { ap, cx, type_cache }
|
||||||
ap,
|
|
||||||
cx,
|
|
||||||
seen_types,
|
|
||||||
type_cache,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn manage_has_expensive_expr_after_last_attr(&mut self) {
|
fn manage_has_expensive_expr_after_last_attr(&mut self) {
|
||||||
@ -288,7 +274,7 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'o
|
|||||||
apa.counter = apa.counter.wrapping_add(1);
|
apa.counter = apa.counter.wrapping_add(1);
|
||||||
apa.has_expensive_expr_after_last_attr = false;
|
apa.has_expensive_expr_after_last_attr = false;
|
||||||
};
|
};
|
||||||
let mut ac = AttrChecker::new(self.cx, self.seen_types, self.type_cache);
|
let mut ac = AttrChecker::new(self.cx, self.type_cache);
|
||||||
if ac.has_sig_drop_attr(self.cx.typeck_results().expr_ty(expr)) {
|
if ac.has_sig_drop_attr(self.cx.typeck_results().expr_ty(expr)) {
|
||||||
if let hir::StmtKind::Let(local) = self.ap.curr_stmt.kind
|
if let hir::StmtKind::Let(local) = self.ap.curr_stmt.kind
|
||||||
&& let hir::PatKind::Binding(_, hir_id, ident, _) = local.pat.kind
|
&& let hir::PatKind::Binding(_, hir_id, ident, _) = local.pat.kind
|
||||||
|
Loading…
x
Reference in New Issue
Block a user