summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/dereference.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /src/tools/clippy/clippy_lints/src/dereference.rs
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/clippy/clippy_lints/src/dereference.rs')
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs58
1 files changed, 36 insertions, 22 deletions
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index b27ffe73f..12f2f37e3 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -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, ParamEnv, ParamTy,
- PredicateKind, ProjectionPredicate, Ty, TyCtxt, TypeVisitableExt, TypeckResults,
+ self, Binder, BoundVariableKind, ClauseKind, EarlyBinder, FnSig, GenericArgKind, List, ParamEnv, ParamTy,
+ ProjectionPredicate, Ty, TyCtxt, TypeVisitableExt, TypeckResults,
};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{symbol::sym, Span, Symbol};
@@ -56,9 +56,11 @@ declare_clippy_lint! {
/// let b = &*a;
/// ```
///
- /// This lint excludes:
+ /// This lint excludes all of:
/// ```rust,ignore
/// let _ = d.unwrap().deref();
+ /// let _ = Foo::deref(&foo);
+ /// let _ = <Foo as Deref>::deref(&foo);
/// ```
#[clippy::version = "1.44.0"]
pub EXPLICIT_DEREF_METHODS,
@@ -355,15 +357,17 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
// start auto-deref.
// 4. If the chain of non-user-defined derefs ends with a mutable re-borrow, and re-borrow
// adjustments will not be inserted automatically, then leave one further reference to avoid
- // moving a mutable borrow.
- // e.g.
- // fn foo<T>(x: &mut Option<&mut T>, y: &mut T) {
- // let x = match x {
- // // Removing the borrow will cause `x` to be moved
- // Some(x) => &mut *x,
- // None => y
- // };
- // }
+ // moving a mutable borrow. e.g.
+ //
+ // ```rust
+ // fn foo<T>(x: &mut Option<&mut T>, y: &mut T) {
+ // let x = match x {
+ // // Removing the borrow will cause `x` to be moved
+ // Some(x) => &mut *x,
+ // None => y
+ // };
+ // }
+ // ```
let deref_msg =
"this expression creates a reference which is immediately dereferenced by the compiler";
let borrow_msg = "this expression borrows a value the compiler would automatically borrow";
@@ -1133,7 +1137,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
let projection_predicates = predicates
.iter()
.filter_map(|predicate| {
- if let PredicateKind::Clause(Clause::Projection(projection_predicate)) = predicate.kind().skip_binder() {
+ if let ClauseKind::Projection(projection_predicate) = predicate.kind().skip_binder() {
Some(projection_predicate)
} else {
None
@@ -1147,7 +1151,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
if predicates
.iter()
.filter_map(|predicate| {
- if let PredicateKind::Clause(Clause::Trait(trait_predicate)) = predicate.kind().skip_binder()
+ if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder()
&& trait_predicate.trait_ref.self_ty() == param_ty.to_ty(cx.tcx)
{
Some(trait_predicate.trait_ref.def_id)
@@ -1209,7 +1213,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
}
predicates.iter().all(|predicate| {
- if let PredicateKind::Clause(Clause::Trait(trait_predicate)) = predicate.kind().skip_binder()
+ if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder()
&& cx.tcx.is_diagnostic_item(sym::IntoIterator, trait_predicate.trait_ref.def_id)
&& let ty::Param(param_ty) = trait_predicate.self_ty().kind()
&& let GenericArgKind::Type(ty) = substs_with_referent_ty[param_ty.index as usize].unpack()
@@ -1219,7 +1223,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
return false;
}
- let predicate = EarlyBinder(predicate).subst(cx.tcx, &substs_with_referent_ty);
+ let predicate = EarlyBinder::bind(predicate).subst(cx.tcx, &substs_with_referent_ty);
let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
let infcx = cx.tcx.infer_ctxt().build();
infcx.predicate_must_hold_modulo_regions(&obligation)
@@ -1292,8 +1296,8 @@ fn referent_used_exactly_once<'tcx>(
possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
reference: &Expr<'tcx>,
) -> bool {
- let mir = enclosing_mir(cx.tcx, reference.hir_id);
- if let Some(local) = expr_local(cx.tcx, reference)
+ if let Some(mir) = enclosing_mir(cx.tcx, reference.hir_id)
+ && let Some(local) = expr_local(cx.tcx, reference)
&& let [location] = *local_assignments(mir, local).as_slice()
&& let Some(statement) = mir.basic_blocks[location.block].statements.get(location.statement_index)
&& let StatementKind::Assign(box (_, Rvalue::Ref(_, _, place))) = statement.kind
@@ -1424,6 +1428,7 @@ fn ty_auto_deref_stability<'tcx>(
continue;
},
ty::Param(_) => TyPosition::new_deref_stable_for_result(precedence, ty),
+ ty::Alias(ty::Weak, _) => unreachable!("should have been normalized away above"),
ty::Alias(ty::Inherent, _) => unreachable!("inherent projection should have been normalized away above"),
ty::Alias(ty::Projection, _) if ty.has_non_region_param() => {
TyPosition::new_deref_stable_for_result(precedence, ty)
@@ -1480,7 +1485,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
target_mut,
} => {
let mut app = Applicability::MachineApplicable;
- let (expr_str, expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
+ let (expr_str, _expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
let ty = cx.typeck_results().expr_ty(expr);
let (_, ref_count) = peel_mid_ty_refs(ty);
let deref_str = if ty_changed_count >= ref_count && ref_count != 0 {
@@ -1503,11 +1508,20 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
"&"
};
- let expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX {
- format!("({expr_str})")
+ // expr_str (the suggestion) is never shown if is_final_ufcs is true, since it's
+ // `expr.kind == ExprKind::Call`. Therefore, this is, afaik, always unnecessary.
+ /*
+ expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX {
+ Cow::Owned(format!("({expr_str})"))
} else {
- expr_str.into_owned()
+ expr_str
};
+ */
+
+ // Fix #10850, do not lint if it's `Foo::deref` instead of `foo.deref()`.
+ if is_final_ufcs {
+ return;
+ }
span_lint_and_sugg(
cx,