summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/dereference.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/clippy_lints/src/dereference.rs')
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs105
1 files changed, 69 insertions, 36 deletions
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 05f2b92c0..7f3f26bed 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -3,7 +3,7 @@ use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exact
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
use clippy_utils::sugg::has_enclosing_paren;
-use clippy_utils::ty::{expr_sig, is_copy, peel_mid_ty_refs, ty_sig, variant_of_res};
+use clippy_utils::ty::{adt_and_variant_of_res, expr_sig, is_copy, peel_mid_ty_refs, ty_sig};
use clippy_utils::{
fn_def_id, get_parent_expr, get_parent_expr_for_hir, is_lint_allowed, path_to_local, walk_to_expr_usage,
};
@@ -26,8 +26,8 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::{Rvalue, StatementKind};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
use rustc_middle::ty::{
- self, Binder, BoundVariableKind, Clause, EarlyBinder, FnSig, GenericArgKind, List, ParamTy, PredicateKind,
- ProjectionPredicate, Ty, TyCtxt, TypeVisitable, TypeckResults,
+ self, Binder, BoundVariableKind, Clause, EarlyBinder, FnSig, GenericArgKind, List, ParamEnv, ParamTy,
+ PredicateKind, ProjectionPredicate, Ty, TyCtxt, TypeVisitableExt, TypeckResults,
};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{symbol::sym, Span, Symbol};
@@ -735,8 +735,8 @@ fn walk_parents<'tcx>(
span,
..
}) if span.ctxt() == ctxt => {
- let ty = cx.tcx.type_of(owner_id.def_id);
- Some(ty_auto_deref_stability(cx, ty, precedence).position_for_result(cx))
+ let ty = cx.tcx.type_of(owner_id.def_id).subst_identity();
+ Some(ty_auto_deref_stability(cx.tcx, cx.param_env, ty, precedence).position_for_result(cx))
},
Node::Item(&Item {
@@ -759,8 +759,8 @@ fn walk_parents<'tcx>(
}) if span.ctxt() == ctxt => {
let output = cx
.tcx
- .erase_late_bound_regions(cx.tcx.fn_sig(owner_id.to_def_id()).output());
- Some(ty_auto_deref_stability(cx, output, precedence).position_for_result(cx))
+ .erase_late_bound_regions(cx.tcx.fn_sig(owner_id).subst_identity().output());
+ Some(ty_auto_deref_stability(cx.tcx, cx.param_env, output, precedence).position_for_result(cx))
},
Node::ExprField(field) if field.span.ctxt() == ctxt => match get_parent_expr_for_hir(cx, field.hir_id) {
@@ -768,31 +768,44 @@ fn walk_parents<'tcx>(
hir_id,
kind: ExprKind::Struct(path, ..),
..
- }) => variant_of_res(cx, cx.qpath_res(path, *hir_id))
- .and_then(|variant| variant.fields.iter().find(|f| f.name == field.ident.name))
- .map(|field_def| {
- ty_auto_deref_stability(cx, cx.tcx.type_of(field_def.did), precedence).position_for_arg()
+ }) => adt_and_variant_of_res(cx, cx.qpath_res(path, *hir_id))
+ .and_then(|(adt, variant)| {
+ variant
+ .fields
+ .iter()
+ .find(|f| f.name == field.ident.name)
+ .map(|f| (adt, f))
+ })
+ .map(|(adt, field_def)| {
+ ty_auto_deref_stability(
+ cx.tcx,
+ // Use the param_env of the target type.
+ cx.tcx.param_env(adt.did()),
+ cx.tcx.type_of(field_def.did).subst_identity(),
+ precedence,
+ )
+ .position_for_arg()
}),
_ => None,
},
Node::Expr(parent) if parent.span.ctxt() == ctxt => match parent.kind {
ExprKind::Ret(_) => {
- let owner_id = cx.tcx.hir().body_owner(cx.enclosing_body.unwrap());
+ let owner_id = cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap());
Some(
if let Node::Expr(
closure_expr @ Expr {
kind: ExprKind::Closure(closure),
..
},
- ) = cx.tcx.hir().get(owner_id)
+ ) = cx.tcx.hir().get_by_def_id(owner_id)
{
closure_result_position(cx, closure, cx.typeck_results().expr_ty(closure_expr), precedence)
} else {
let output = cx
.tcx
- .erase_late_bound_regions(cx.tcx.fn_sig(cx.tcx.hir().local_def_id(owner_id)).output());
- ty_auto_deref_stability(cx, output, precedence).position_for_result(cx)
+ .erase_late_bound_regions(cx.tcx.fn_sig(owner_id).subst_identity().output());
+ ty_auto_deref_stability(cx.tcx, cx.param_env, output, precedence).position_for_result(cx)
},
)
},
@@ -835,15 +848,20 @@ fn walk_parents<'tcx>(
msrv,
)
} else {
- ty_auto_deref_stability(cx, cx.tcx.erase_late_bound_regions(ty), precedence)
- .position_for_arg()
+ ty_auto_deref_stability(
+ cx.tcx,
+ // Use the param_env of the target function.
+ sig.predicates_id().map_or(ParamEnv::empty(), |id| cx.tcx.param_env(id)),
+ cx.tcx.erase_late_bound_regions(ty),
+ precedence
+ ).position_for_arg()
}
},
}
})
}),
ExprKind::MethodCall(method, receiver, args, _) => {
- let id = cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap();
+ let fn_id = cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap();
if receiver.hir_id == child_id {
// Check for calls to trait methods where the trait is implemented on a reference.
// Two cases need to be handled:
@@ -852,13 +870,17 @@ fn walk_parents<'tcx>(
// priority.
if e.hir_id != child_id {
return Some(Position::ReborrowStable(precedence))
- } else if let Some(trait_id) = cx.tcx.trait_of_item(id)
+ } else if let Some(trait_id) = cx.tcx.trait_of_item(fn_id)
&& let arg_ty = cx.tcx.erase_regions(cx.typeck_results().expr_ty_adjusted(e))
&& let ty::Ref(_, sub_ty, _) = *arg_ty.kind()
&& let subs = cx
.typeck_results()
.node_substs_opt(parent.hir_id).map(|subs| &subs[1..]).unwrap_or_default()
- && let impl_ty = if cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref() {
+ && let impl_ty = if cx.tcx.fn_sig(fn_id)
+ .subst_identity()
+ .skip_binder()
+ .inputs()[0].is_ref()
+ {
// Trait methods taking `&self`
sub_ty
} else {
@@ -879,10 +901,13 @@ fn walk_parents<'tcx>(
return Some(Position::MethodReceiver);
}
args.iter().position(|arg| arg.hir_id == child_id).map(|i| {
- let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i + 1];
+ let ty = cx.tcx.fn_sig(fn_id).subst_identity().input(i + 1);
// `e.hir_id == child_id` for https://github.com/rust-lang/rust-clippy/issues/9739
// `method.args.is_none()` for https://github.com/rust-lang/rust-clippy/issues/9782
- if e.hir_id == child_id && method.args.is_none() && let ty::Param(param_ty) = ty.kind() {
+ if e.hir_id == child_id
+ && method.args.is_none()
+ && let ty::Param(param_ty) = ty.skip_binder().kind()
+ {
needless_borrow_impl_arg_position(
cx,
possible_borrowers,
@@ -895,8 +920,10 @@ fn walk_parents<'tcx>(
)
} else {
ty_auto_deref_stability(
- cx,
- cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).input(i + 1)),
+ cx.tcx,
+ // Use the param_env of the target function.
+ cx.tcx.param_env(fn_id),
+ cx.tcx.erase_late_bound_regions(ty),
precedence,
)
.position_for_arg()
@@ -1022,7 +1049,7 @@ fn binding_ty_auto_deref_stability<'tcx>(
))
.is_sized(cx.tcx, cx.param_env.without_caller_bounds()),
),
- TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => {
+ TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err(_) => {
Position::ReborrowStable(precedence)
},
};
@@ -1038,7 +1065,7 @@ fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool {
if self.0
|| matches!(
ty.kind,
- TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(_) | TyKind::Err
+ TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(_) | TyKind::Err(_)
)
{
self.0 = true;
@@ -1093,7 +1120,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
let sized_trait_def_id = cx.tcx.lang_items().sized_trait();
let Some(callee_def_id) = fn_def_id(cx, parent) else { return Position::Other(precedence) };
- let fn_sig = cx.tcx.fn_sig(callee_def_id).skip_binder();
+ let fn_sig = cx.tcx.fn_sig(callee_def_id).subst_identity().skip_binder();
let substs_with_expr_ty = cx
.typeck_results()
.node_substs(if let ExprKind::Call(callee, _) = parent.kind {
@@ -1221,7 +1248,7 @@ fn has_ref_mut_self_method(cx: &LateContext<'_>, trait_def_id: DefId) -> bool {
.in_definition_order()
.any(|assoc_item| {
if assoc_item.fn_has_self_parameter {
- let self_ty = cx.tcx.fn_sig(assoc_item.def_id).skip_binder().inputs()[0];
+ let self_ty = cx.tcx.fn_sig(assoc_item.def_id).subst_identity().skip_binder().inputs()[0];
matches!(self_ty.kind(), ty::Ref(_, _, Mutability::Mut))
} else {
false
@@ -1330,10 +1357,10 @@ fn replace_types<'tcx>(
&& let Some(term_ty) = projection_predicate.term.ty()
&& let ty::Param(term_param_ty) = term_ty.kind()
{
- let item_def_id = projection_predicate.projection_ty.def_id;
- let assoc_item = cx.tcx.associated_item(item_def_id);
- let projection = cx.tcx
- .mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(new_ty, []));
+ let projection = cx.tcx.mk_ty_from_kind(ty::Alias(
+ ty::Projection,
+ projection_predicate.projection_ty.with_self_ty(cx.tcx, new_ty),
+ ));
if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection)
&& substs[term_param_ty.index as usize] != ty::GenericArg::from(projected_ty)
@@ -1378,11 +1405,18 @@ impl<'tcx> TyPosition<'tcx> {
}
// Checks whether a type is stable when switching to auto dereferencing,
-fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedence: i8) -> TyPosition<'tcx> {
+fn ty_auto_deref_stability<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ ty: Ty<'tcx>,
+ precedence: i8,
+) -> TyPosition<'tcx> {
let ty::Ref(_, mut ty, _) = *ty.kind() else {
return Position::Other(precedence).into();
};
+ ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty);
+
loop {
break match *ty.kind() {
ty::Ref(_, ref_ty, _) => {
@@ -1419,12 +1453,11 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
| ty::FnDef(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Closure(..)
| ty::Never
| ty::Tuple(_)
- | ty::Alias(ty::Projection, _) => {
- Position::DerefStable(precedence, ty.is_sized(cx.tcx, cx.param_env.without_caller_bounds())).into()
- },
+ | ty::Alias(ty::Projection, _) => Position::DerefStable(precedence, ty.is_sized(tcx, param_env)).into(),
};
}
}