Rollup merge of #151850 - frank-king:refactor/pin-coerce-2, r=jackh726

refactor: add an `enum DerefAdjustKind` in favor of `Option<OverloadedDeref>`

Part of rust-lang/rust#149130.

r? jackh726
This commit is contained in:
Jonathan Brouwer 2026-01-31 15:17:05 +01:00 committed by GitHub
commit 1b7a7c7514
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 90 additions and 72 deletions

View file

@ -6,7 +6,7 @@ use itertools::Itertools;
use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind};
use rustc_infer::infer::InferOk;
use rustc_infer::traits::PredicateObligations;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind, OverloadedDeref};
use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
@ -45,22 +45,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty()));
let steps: Vec<_> = steps
.iter()
.map(|&(source, kind)| {
if let AutoderefKind::Overloaded = kind {
self.try_overloaded_deref(autoderef.span(), source).and_then(
|InferOk { value: method, obligations: o }| {
.map(|&(source, kind)| match kind {
AutoderefKind::Overloaded => {
self.try_overloaded_deref(autoderef.span(), source)
.and_then(|InferOk { value: method, obligations: o }| {
obligations.extend(o);
// FIXME: we should assert the sig is &T here... there's no reason for this to be fallible.
if let ty::Ref(_, _, mutbl) = *method.sig.output().kind() {
Some(OverloadedDeref { mutbl, span: autoderef.span() })
Some(DerefAdjustKind::Overloaded(OverloadedDeref {
mutbl,
span: autoderef.span(),
}))
} else {
None
}
},
)
} else {
None
})
.unwrap_or(DerefAdjustKind::Builtin)
}
AutoderefKind::Builtin => DerefAdjustKind::Builtin,
})
.zip_eq(targets)
.map(|(autoderef, target)| Adjustment { kind: Adjust::Deref(autoderef), target })

View file

@ -50,7 +50,8 @@ use rustc_infer::traits::{
};
use rustc_middle::span_bug;
use rustc_middle::ty::adjustment::{
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion,
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, DerefAdjustKind,
PointerCoercion,
};
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
@ -595,7 +596,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
let mutbl = AutoBorrowMutability::new(mutbl_b, AllowTwoPhase::No);
Some((
Adjustment { kind: Adjust::Deref(None), target: ty_a },
Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: ty_a },
Adjustment {
kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
target: Ty::new_ref(self.tcx, r_borrow, ty_a, mutbl_b),
@ -606,7 +607,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
coerce_mutbls(mt_a, mt_b)?;
Some((
Adjustment { kind: Adjust::Deref(None), target: ty_a },
Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: ty_a },
Adjustment {
kind: Adjust::Borrow(AutoBorrow::RawPtr(mt_b)),
target: Ty::new_ptr(self.tcx, ty_a, mt_b),
@ -936,7 +937,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
self.unify_and(
a_raw,
b,
[Adjustment { kind: Adjust::Deref(None), target: mt_a.ty }],
[Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: mt_a.ty }],
Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b)),
ForceLeakCheck::No,
)

View file

@ -22,6 +22,7 @@ use rustc_middle::hir::place::ProjectionKind;
pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection};
use rustc_middle::mir::FakeReadCause;
use rustc_middle::thir::DerefPatBorrowMode;
use rustc_middle::ty::adjustment::DerefAdjustKind;
use rustc_middle::ty::{
self, BorrowKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, adjustment,
};
@ -733,14 +734,14 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
self.consume_or_copy(&place_with_id, place_with_id.hir_id);
}
adjustment::Adjust::Deref(None) => {}
adjustment::Adjust::Deref(DerefAdjustKind::Builtin) => {}
// Autoderefs for overloaded Deref calls in fact reference
// their receiver. That is, if we have `(*x)` where `x`
// is of type `Rc<T>`, then this in fact is equivalent to
// `x.deref()`. Since `deref()` is declared with `&self`,
// this is an autoref of `x`.
adjustment::Adjust::Deref(Some(ref deref)) => {
adjustment::Adjust::Deref(DerefAdjustKind::Overloaded(deref)) => {
let bk = ty::BorrowKind::from_mutbl(deref.mutbl);
self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk);
}
@ -1272,9 +1273,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
{
let target = self.cx.resolve_vars_if_possible(adjustment.target);
match adjustment.kind {
adjustment::Adjust::Deref(overloaded) => {
adjustment::Adjust::Deref(deref_kind) => {
// Equivalent to *expr or something similar.
let base = if let Some(deref) = overloaded {
let base = if let DerefAdjustKind::Overloaded(deref) = deref_kind {
let ref_ty = Ty::new_ref(
self.cx.tcx(),
self.cx.tcx().lifetimes.re_erased,

View file

@ -20,7 +20,9 @@ use rustc_hir_analysis::hir_ty_lowering::{
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
use rustc_infer::infer::{DefineOpaqueTypes, InferResult};
use rustc_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
use rustc_middle::ty::adjustment::{
Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, DerefAdjustKind,
};
use rustc_middle::ty::{
self, AdtKind, CanonicalUserType, GenericArgsRef, GenericParamDefKind, IsIdentity,
SizedTraitKind, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitableExt, UserArgs,
@ -266,7 +268,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target);
}
}
Adjust::Deref(Some(overloaded_deref)) => {
Adjust::Deref(DerefAdjustKind::Overloaded(overloaded_deref)) => {
self.enforce_context_effects(
None,
expr.span,
@ -274,7 +276,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.mk_args(&[expr_ty.into()]),
);
}
Adjust::Deref(None) => {
Adjust::Deref(DerefAdjustKind::Builtin) => {
// FIXME(const_trait_impl): We *could* enforce `&T: [const] Deref` here.
}
Adjust::Pointer(_pointer_coercion) => {

View file

@ -4,8 +4,8 @@ use rustc_infer::infer::InferOk;
use rustc_infer::traits::{Obligation, ObligationCauseCode};
use rustc_middle::span_bug;
use rustc_middle::ty::adjustment::{
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, OverloadedDeref,
PointerCoercion,
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, DerefAdjustKind,
OverloadedDeref, PointerCoercion,
};
use rustc_middle::ty::{self, Ty};
use rustc_span::{Span, sym};
@ -298,7 +298,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.typeck_results.borrow_mut().adjustments_mut().remove(expr.hir_id);
if let Some(mut adjustments) = previous_adjustments {
for adjustment in &mut adjustments {
if let Adjust::Deref(Some(ref mut deref)) = adjustment.kind
if let Adjust::Deref(DerefAdjustKind::Overloaded(ref mut deref)) =
adjustment.kind
&& let Some(ok) = self.try_mutable_overloaded_place_op(
expr.span,
source,

View file

@ -1,7 +1,9 @@
use rustc_ast::{BorrowKind, UnOp};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::{Expr, ExprKind, Mutability, find_attr};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, OverloadedDeref};
use rustc_middle::ty::adjustment::{
Adjust, Adjustment, AutoBorrow, DerefAdjustKind, OverloadedDeref,
};
use rustc_session::{declare_lint, declare_lint_pass};
use crate::lints::{
@ -165,12 +167,14 @@ fn peel_derefs_adjustments<'a>(mut adjs: &'a [Adjustment<'a>]) -> &'a [Adjustmen
/// an implicit borrow (or has an implicit borrow via an overloaded deref).
fn has_implicit_borrow(Adjustment { kind, .. }: &Adjustment<'_>) -> Option<(Mutability, bool)> {
match kind {
&Adjust::Deref(Some(OverloadedDeref { mutbl, .. })) => Some((mutbl, true)),
&Adjust::Deref(DerefAdjustKind::Overloaded(OverloadedDeref { mutbl, .. })) => {
Some((mutbl, true))
}
&Adjust::Borrow(AutoBorrow::Ref(mutbl)) => Some((mutbl.into(), false)),
Adjust::NeverToAny
| Adjust::Pointer(..)
| Adjust::ReborrowPin(..)
| Adjust::Deref(None)
| Adjust::Deref(DerefAdjustKind::Builtin)
| Adjust::Borrow(AutoBorrow::RawPtr(..)) => None,
}
}

View file

@ -1,7 +1,7 @@
use rustc_hir::def::DefKind;
use rustc_hir::{Expr, ExprKind};
use rustc_middle::ty;
use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind};
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::sym;
@ -114,7 +114,10 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
// If there is any user defined auto-deref step, then we don't want to warn.
// https://github.com/rust-lang/rust-clippy/issues/9272
if arg_adjustments.iter().any(|adj| matches!(adj.kind, Adjust::Deref(Some(_)))) {
if arg_adjustments
.iter()
.any(|adj| matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Overloaded(_))))
{
return;
}

View file

@ -97,7 +97,7 @@ pub enum Adjust {
NeverToAny,
/// Dereference once, producing a place.
Deref(Option<OverloadedDeref>),
Deref(DerefAdjustKind),
/// Take the address and produce either a `&` or `*` pointer.
Borrow(AutoBorrow),
@ -108,6 +108,12 @@ pub enum Adjust {
ReborrowPin(hir::Mutability),
}
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub enum DerefAdjustKind {
Builtin,
Overloaded(OverloadedDeref),
}
/// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`
/// call, with the signature `&'a T -> &'a U` or `&'a mut T -> &'a mut U`.
/// The target type is `U` in both cases, with the region and mutability

View file

@ -14,7 +14,7 @@ use rustc_middle::middle::region;
use rustc_middle::mir::{self, AssignOp, BinOp, BorrowKind, UnOp};
use rustc_middle::thir::*;
use rustc_middle::ty::adjustment::{
Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCoercion,
Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, DerefAdjustKind, PointerCoercion,
};
use rustc_middle::ty::{
self, AdtKind, GenericArgs, InlineConstArgs, InlineConstArgsParts, ScalarInt, Ty, UpvarArgs,
@ -140,11 +140,11 @@ impl<'tcx> ThirBuildCx<'tcx> {
}
Adjust::NeverToAny if adjustment.target.is_never() => return expr,
Adjust::NeverToAny => ExprKind::NeverToAny { source: self.thir.exprs.push(expr) },
Adjust::Deref(None) => {
Adjust::Deref(DerefAdjustKind::Builtin) => {
adjust_span(&mut expr);
ExprKind::Deref { arg: self.thir.exprs.push(expr) }
}
Adjust::Deref(Some(deref)) => {
Adjust::Deref(DerefAdjustKind::Overloaded(deref)) => {
// We don't need to do call adjust_span here since
// deref coercions always start with a built-in deref.
let call_def_id = deref.method_call(self.tcx);

View file

@ -12,7 +12,7 @@ use rustc_hir::{
};
use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, DerefAdjustKind};
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
use rustc_middle::ty::{
self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Term, TermKind,
@ -615,7 +615,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// first adjustment was not a builtin deref.
let adjustment = match typeck_results.expr_adjustments(receiver) {
[
Adjustment { kind: Adjust::Deref(None), target: _ },
Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: _ },
..,
Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), target: _ },
] => "",

View file

@ -10,7 +10,7 @@ use rustc_hir::attrs::AttributeKind;
use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, GenericArgs, Param, PatKind, QPath, Safety, TyKind, find_attr};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind};
use rustc_middle::ty::{
self, Binder, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, Ty, TypeVisitableExt, TypeckResults,
};
@ -236,7 +236,7 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx
.iter()
.rev()
.fold(0, |acc, adjustment| match adjustment.kind {
Adjust::Deref(Some(_)) => acc + 1,
Adjust::Deref(DerefAdjustKind::Overloaded(_)) => acc + 1,
Adjust::Deref(_) if acc > 0 => acc + 1,
_ => acc,
})

View file

@ -24,7 +24,7 @@ use rustc_errors::SuggestionStyle::{CompletelyHidden, ShowCode};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::{Expr, ExprKind, LangItem, RustcVersion, find_attr};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind};
use rustc_middle::ty::{self, GenericArg, List, TraitRef, Ty, TyCtxt, Upcast};
use rustc_session::impl_lint_pass;
use rustc_span::edition::Edition::Edition2021;
@ -704,12 +704,12 @@ where
let mut n_needed = 0;
loop {
if let Some(Adjustment {
kind: Adjust::Deref(overloaded_deref),
kind: Adjust::Deref(deref),
target,
}) = iter.next()
{
n_total += 1;
if overloaded_deref.is_some() {
if let DerefAdjustKind::Overloaded(..) = deref {
n_needed = n_total;
}
ty = *target;

View file

@ -12,7 +12,7 @@ use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_hir::{Closure, Expr, ExprKind, HirId, LetStmt, Mutability, UnOp};
use rustc_lint::LateContext;
use rustc_middle::hir::nested_filter::OnlyBodies;
use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind};
use rustc_span::Symbol;
use rustc_span::symbol::sym;
@ -88,7 +88,7 @@ fn try_parse_iter_expr(cx: &LateContext<'_>, mut e: &Expr<'_>) -> Option<IterExp
.typeck_results()
.expr_adjustments(e)
.iter()
.any(|a| matches!(a.kind, Adjust::Deref(Some(..))))
.any(|a| matches!(a.kind, Adjust::Deref(DerefAdjustKind::Overloaded(..))))
{
// Custom deref impls need to borrow the whole value as it's captured by reference
can_move = false;

View file

@ -10,7 +10,7 @@ use rustc_hir::{self as hir, LangItem};
use rustc_lint::LateContext;
use rustc_middle::mir::{Mutability, Pinnedness};
use rustc_middle::ty;
use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind};
use rustc_span::symbol::Ident;
use rustc_span::{Span, sym};
@ -73,7 +73,7 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_
&& cx.tcx.lang_items().clone_trait() == Some(trait_id)
// no autoderefs
&& !cx.typeck_results().expr_adjustments(obj).iter()
.any(|a| matches!(a.kind, Adjust::Deref(Some(..))))
.any(|a| matches!(a.kind, Adjust::Deref(DerefAdjustKind::Overloaded(..))))
{
let obj_ty = cx.typeck_results().expr_ty(obj);
if let ty::Ref(_, ty, mutability) = obj_ty.kind() {

View file

@ -58,7 +58,7 @@ pub(super) fn check(
.iter()
.map(|x| &x.kind)
.collect::<Box<[_]>>()
&& let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj
&& let [ty::adjustment::Adjust::Deref(ty::adjustment::DerefAdjustKind::Builtin), ty::adjustment::Adjust::Borrow(_)] = *adj
&& let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap()
&& let Some(method_name) = cx.tcx.get_diagnostic_name(method_did)
{

View file

@ -4,7 +4,7 @@ use rustc_ast::BorrowKind;
use rustc_errors::{Applicability, Diag};
use rustc_hir::{Expr, ExprKind, Node, QPath};
use rustc_lint::LateContext;
use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind};
use rustc_span::sym;
use super::SWAP_WITH_TEMPORARY;
@ -47,7 +47,7 @@ impl<'tcx> ArgKind<'tcx> {
&& let adjustments = cx.typeck_results().expr_adjustments(arg)
&& adjustments
.first()
.is_some_and(|adj| matches!(adj.kind, Adjust::Deref(None)))
.is_some_and(|adj| matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Builtin)))
&& adjustments
.last()
.is_some_and(|adj| matches!(adj.kind, Adjust::Borrow(_)))

View file

@ -4,7 +4,7 @@ use clippy_utils::source::snippet;
use rustc_errors::Applicability;
use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind};
use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::{self, ExistentialPredicate, Ty};
use rustc_span::{Span, sym};
@ -58,7 +58,7 @@ pub(super) fn check(cx: &LateContext<'_>, receiver: &Expr<'_>, call_span: Span)
|diag| {
let derefs = recv_adjusts
.iter()
.filter(|adj| matches!(adj.kind, Adjust::Deref(None)))
.filter(|adj| matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Builtin)))
.count();
diag.note(

View file

@ -14,7 +14,7 @@ use rustc_hir::{BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::LateContext;
use rustc_middle::mir::Mutability;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind, OverloadedDeref};
use rustc_middle::ty::{
self, ClauseKind, GenericArg, GenericArgKind, GenericArgsRef, ParamTy, ProjectionPredicate, TraitPredicate, Ty,
};
@ -78,7 +78,7 @@ fn check_addr_of_expr(
// For matching uses of `Cow::from`
[
Adjustment {
kind: Adjust::Deref(None),
kind: Adjust::Deref(DerefAdjustKind::Builtin),
target: referent_ty,
},
Adjustment {
@ -89,7 +89,7 @@ fn check_addr_of_expr(
// For matching uses of arrays
| [
Adjustment {
kind: Adjust::Deref(None),
kind: Adjust::Deref(DerefAdjustKind::Builtin),
target: referent_ty,
},
Adjustment {
@ -104,11 +104,11 @@ fn check_addr_of_expr(
// For matching everything else
| [
Adjustment {
kind: Adjust::Deref(None),
kind: Adjust::Deref(DerefAdjustKind::Builtin),
target: referent_ty,
},
Adjustment {
kind: Adjust::Deref(Some(OverloadedDeref { .. })),
kind: Adjust::Deref(DerefAdjustKind::Overloaded(OverloadedDeref { .. })),
..
},
Adjustment {

View file

@ -7,7 +7,7 @@ use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{self as hir, LangItem, Node};
use rustc_lint::LateContext;
use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind};
use rustc_middle::ty::{Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
use rustc_span::{Span, Symbol, sym};
@ -161,7 +161,7 @@ fn is_calling_clone(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool {
&& cx.tcx.lang_items().clone_trait().is_some_and(|id| id == trait_id)
// no autoderefs
&& !cx.typeck_results().expr_adjustments(obj).iter()
.any(|a| matches!(a.kind, Adjust::Deref(Some(..))))
.any(|a| matches!(a.kind, Adjust::Deref(DerefAdjustKind::Overloaded(..))))
&& obj.res_local_id() == Some(local_id)
{
true

View file

@ -33,7 +33,7 @@ use rustc_hir::{
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::mir::{ConstValue, UnevaluatedConst};
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind};
use rustc_middle::ty::{
self, AliasTyKind, EarlyBinder, GenericArgs, GenericArgsRef, Instance, Ty, TyCtxt, TypeFolder, TypeSuperFoldable,
TypeckResults, TypingEnv,
@ -907,7 +907,7 @@ fn does_adjust_borrow(adjust: &Adjustment<'_>) -> Option<BorrowCause> {
match adjust.kind {
Adjust::Borrow(_) => Some(BorrowCause::AutoBorrow),
// Custom deref calls `<T as Deref>::deref(&x)` resulting in a borrow.
Adjust::Deref(Some(_)) => Some(BorrowCause::AutoDeref),
Adjust::Deref(DerefAdjustKind::Overloaded(_)) => Some(BorrowCause::AutoDeref),
// All other adjustments read the value.
_ => None,
}

View file

@ -19,7 +19,7 @@ use rustc_hir::intravisit::{Visitor, walk_expr};
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, QPath, UnOp};
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind};
use rustc_span::Symbol;
use std::{cmp, ops};
@ -132,7 +132,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
.typeck_results()
.expr_adjustments(e)
.iter()
.any(|adj| matches!(adj.kind, Adjust::Deref(Some(_))))
.any(|adj| matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Overloaded(_))))
{
self.eagerness |= NoChange;
return;
@ -211,12 +211,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
// 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() =>
if self.cx.typeck_results().expr_ty(e).builtin_deref(true).is_none() =>
{
self.eagerness |= NoChange;
},

View file

@ -108,7 +108,7 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::hir::place::PlaceBase;
use rustc_middle::lint::LevelAndSource;
use rustc_middle::mir::{AggregateKind, Operand, RETURN_PLACE, Rvalue, StatementKind, TerminatorKind};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, PointerCoercion};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, DerefAdjustKind, PointerCoercion};
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::ty::{
self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, GenericArgKind, GenericArgsRef, IntTy, Ty, TyCtxt,
@ -477,8 +477,8 @@ pub fn expr_custom_deref_adjustment(cx: &LateContext<'_>, e: &Expr<'_>) -> Optio
.expr_adjustments(e)
.iter()
.find_map(|a| match a.kind {
Adjust::Deref(Some(d)) => Some(Some(d.mutbl)),
Adjust::Deref(None) => None,
Adjust::Deref(DerefAdjustKind::Overloaded(d)) => Some(Some(d.mutbl)),
Adjust::Deref(DerefAdjustKind::Builtin) => None,
_ => Some(None),
})
.and_then(|x| x)
@ -3537,7 +3537,9 @@ pub fn expr_adjustment_requires_coercion(cx: &LateContext<'_>, expr: &Expr<'_>)
cx.typeck_results().expr_adjustments(expr).iter().any(|adj| {
matches!(
adj.kind,
Adjust::Deref(Some(_)) | Adjust::Pointer(PointerCoercion::Unsize) | Adjust::NeverToAny
Adjust::Deref(DerefAdjustKind::Overloaded(_))
| Adjust::Pointer(PointerCoercion::Unsize)
| Adjust::NeverToAny
)
})
}

View file

@ -17,7 +17,7 @@ use rustc_lint::LateContext;
use rustc_middle::mir::ConstValue;
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::traits::EvaluationResult;
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind};
use rustc_middle::ty::layout::ValidityRequirement;
use rustc_middle::ty::{
self, AdtDef, AliasTy, AssocItem, AssocTag, Binder, BoundRegion, BoundVarIndexKind, FnSig, GenericArg,
@ -1345,6 +1345,7 @@ pub fn get_field_idx_by_name(ty: Ty<'_>, name: Symbol) -> Option<usize> {
pub fn adjust_derefs_manually_drop<'tcx>(adjustments: &'tcx [Adjustment<'tcx>], mut ty: Ty<'tcx>) -> bool {
adjustments.iter().any(|a| {
let ty = mem::replace(&mut ty, a.target);
matches!(a.kind, Adjust::Deref(Some(op)) if op.mutbl == Mutability::Mut) && is_manually_drop(ty)
matches!(a.kind, Adjust::Deref(DerefAdjustKind::Overloaded(op)) if op.mutbl == Mutability::Mut)
&& is_manually_drop(ty)
})
}