use crate::ty::{all_predicates_of, is_copy};
use crate::visitors::is_const_evaluatable;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor};
+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};
}
/// Determine the eagerness of the given function call.
-fn fn_eagerness<'tcx>(
- cx: &LateContext<'tcx>,
- fn_id: DefId,
- name: Symbol,
- args: &'tcx [Expr<'_>],
-) -> EagernessSuggestion {
+fn fn_eagerness(cx: &LateContext<'_>, fn_id: DefId, name: Symbol, have_one_arg: bool) -> EagernessSuggestion {
use EagernessSuggestion::{Eager, Lazy, NoChange};
let name = name.as_str();
None => return Lazy,
};
- if (name.starts_with("as_") || name == "len" || name == "is_empty") && args.len() == 1 {
+ if (name.starts_with("as_") || name == "len" || name == "is_empty") && have_one_arg {
if matches!(
cx.tcx.crate_name(fn_id.krate),
sym::std | sym::core | sym::alloc | sym::proc_macro
// than marker traits.
// Due to the limited operations on these types functions should be fairly cheap.
if def
- .variants
+ .variants()
.iter()
.flat_map(|v| v.fields.iter())
.any(|x| matches!(cx.tcx.type_of(x.did).peel_refs().kind(), ty::Param(_)))
}
}
-#[allow(clippy::too_many_lines)]
+#[expect(clippy::too_many_lines)]
fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessSuggestion {
struct V<'cx, 'tcx> {
cx: &'cx LateContext<'tcx>,
}
impl<'cx, 'tcx> Visitor<'tcx> for V<'cx, 'tcx> {
- type Map = ErasedMap<'tcx>;
- fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
- NestedVisitorMap::None
- }
-
fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
use EagernessSuggestion::{ForceNoChange, Lazy, NoChange};
if self.eagerness == ForceNoChange {
},
args,
) => match self.cx.qpath_res(path, hir_id) {
- Res::Def(DefKind::Ctor(..) | DefKind::Variant, _) | Res::SelfCtor(_) => (),
+ Res::Def(DefKind::Ctor(..) | DefKind::Variant, _) | Res::SelfCtor(_) => {
+ if self
+ .cx
+ .typeck_results()
+ .expr_ty(e)
+ .has_significant_drop(self.cx.tcx, self.cx.param_env)
+ {
+ self.eagerness = ForceNoChange;
+ return;
+ }
+ },
Res::Def(_, id) if self.cx.tcx.is_promotable_const_fn(id) => (),
// No need to walk the arguments here, `is_const_evaluatable` already did
Res::Def(..) if is_const_evaluatable(self.cx, e) => {
},
Res::Def(_, id) => match path {
QPath::Resolved(_, p) => {
- self.eagerness |= fn_eagerness(self.cx, id, p.segments.last().unwrap().ident.name, args);
+ self.eagerness |=
+ fn_eagerness(self.cx, id, p.segments.last().unwrap().ident.name, !args.is_empty());
},
QPath::TypeRelative(_, name) => {
- self.eagerness |= fn_eagerness(self.cx, id, name.ident.name, args);
+ self.eagerness |= fn_eagerness(self.cx, id, name.ident.name, !args.is_empty());
},
QPath::LangItem(..) => self.eagerness = Lazy,
},
self.eagerness |= NoChange;
return;
},
- ExprKind::MethodCall(name, _, args, _) => {
+ ExprKind::MethodCall(name, ..) => {
self.eagerness |= self
.cx
.typeck_results()
.type_dependent_def_id(e.hir_id)
- .map_or(Lazy, |id| fn_eagerness(self.cx, id, name.ident.name, args));
+ .map_or(Lazy, |id| fn_eagerness(self.cx, id, name.ident.name, true));
},
ExprKind::Index(_, e) => {
let ty = self.cx.typeck_results().expr_ty_adjusted(e);
| ExprKind::Continue(_)
| ExprKind::Ret(_)
| ExprKind::InlineAsm(_)
- | ExprKind::LlvmInlineAsm(_)
| ExprKind::Yield(..)
| ExprKind::Err => {
self.eagerness = ForceNoChange;
| ExprKind::Let(..)
| ExprKind::If(..)
| ExprKind::Match(..)
- | ExprKind::Closure(..)
+ | ExprKind::Closure { .. }
| ExprKind::Field(..)
| ExprKind::Path(_)
| ExprKind::AddrOf(..)