summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/clippy_utils/src/eager_or_lazy.rs')
-rw-r--r--src/tools/clippy/clippy_utils/src/eager_or_lazy.rs28
1 files changed, 24 insertions, 4 deletions
diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
index 3df40942e..4a845ca63 100644
--- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
+++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
@@ -15,7 +15,8 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{walk_expr, Visitor};
use rustc_hir::{def_id::DefId, Block, Expr, ExprKind, QPath, UnOp};
use rustc_lint::LateContext;
-use rustc_middle::ty::{self, PredicateKind};
+use rustc_middle::ty;
+use rustc_middle::ty::adjustment::Adjust;
use rustc_span::{sym, Symbol};
use std::cmp;
use std::ops;
@@ -73,7 +74,7 @@ fn fn_eagerness(cx: &LateContext<'_>, fn_id: DefId, name: Symbol, have_one_arg:
.flat_map(|v| v.fields.iter())
.any(|x| matches!(cx.tcx.type_of(x.did).subst_identity().peel_refs().kind(), ty::Param(_)))
&& all_predicates_of(cx.tcx, fn_id).all(|(pred, _)| match pred.kind().skip_binder() {
- PredicateKind::Clause(ty::Clause::Trait(pred)) => cx.tcx.trait_def(pred.trait_ref.def_id).is_marker,
+ ty::ClauseKind::Trait(pred) => cx.tcx.trait_def(pred.trait_ref.def_id).is_marker,
_ => true,
})
&& subs.types().all(|x| matches!(x.peel_refs().kind(), ty::Param(_)))
@@ -114,6 +115,20 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
if self.eagerness == ForceNoChange {
return;
}
+
+ // Autoderef through a user-defined `Deref` impl can have side-effects,
+ // so don't suggest changing it.
+ if self
+ .cx
+ .typeck_results()
+ .expr_adjustments(e)
+ .iter()
+ .any(|adj| matches!(adj.kind, Adjust::Deref(Some(_))))
+ {
+ self.eagerness |= NoChange;
+ return;
+ }
+
match e.kind {
ExprKind::Call(
&Expr {
@@ -173,11 +188,15 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
self.eagerness = Lazy;
}
},
-
+ // Custom `Deref` impl might have side effects
+ ExprKind::Unary(UnOp::Deref, e)
+ if self.cx.typeck_results().expr_ty(e).builtin_deref(true).is_none() =>
+ {
+ self.eagerness |= NoChange;
+ },
// Dereferences should be cheap, but dereferencing a raw pointer earlier may not be safe.
ExprKind::Unary(UnOp::Deref, e) if !self.cx.typeck_results().expr_ty(e).is_unsafe_ptr() => (),
ExprKind::Unary(UnOp::Deref, _) => self.eagerness |= NoChange,
-
ExprKind::Unary(_, e)
if matches!(
self.cx.typeck_results().expr_ty(e).kind(),
@@ -191,6 +210,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
ExprKind::Break(..)
| ExprKind::Continue(_)
| ExprKind::Ret(_)
+ | ExprKind::Become(_)
| ExprKind::InlineAsm(_)
| ExprKind::Yield(..)
| ExprKind::Err(_) => {