Auto merge of #12976 - tesuji:fix-explicit_auto_deref, r=xFrednet
Fix some false-positive cases of `explicit_auto_deref` changelog: [`explicit_auto_deref`] Fix some false-positive cases Fix part of #9841 Fix #12969 r? xFrednet
This commit is contained in:
commit
0f4035fde3
@ -3,7 +3,8 @@
|
|||||||
use clippy_utils::sugg::has_enclosing_paren;
|
use clippy_utils::sugg::has_enclosing_paren;
|
||||||
use clippy_utils::ty::{implements_trait, is_manually_drop, peel_mid_ty_refs};
|
use clippy_utils::ty::{implements_trait, is_manually_drop, peel_mid_ty_refs};
|
||||||
use clippy_utils::{
|
use clippy_utils::{
|
||||||
expr_use_ctxt, get_parent_expr, is_block_like, is_lint_allowed, path_to_local, DefinedTy, ExprUseNode,
|
expr_use_ctxt, get_parent_expr, is_block_like, is_lint_allowed, path_to_local, peel_middle_ty_refs, DefinedTy,
|
||||||
|
ExprUseNode,
|
||||||
};
|
};
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use rustc_ast::util::parser::{PREC_PREFIX, PREC_UNAMBIGUOUS};
|
use rustc_ast::util::parser::{PREC_PREFIX, PREC_UNAMBIGUOUS};
|
||||||
@ -175,6 +176,7 @@ struct StateData<'tcx> {
|
|||||||
adjusted_ty: Ty<'tcx>,
|
adjusted_ty: Ty<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct DerefedBorrow {
|
struct DerefedBorrow {
|
||||||
count: usize,
|
count: usize,
|
||||||
msg: &'static str,
|
msg: &'static str,
|
||||||
@ -182,6 +184,7 @@ struct DerefedBorrow {
|
|||||||
for_field_access: Option<Symbol>,
|
for_field_access: Option<Symbol>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
enum State {
|
enum State {
|
||||||
// Any number of deref method calls.
|
// Any number of deref method calls.
|
||||||
DerefMethod {
|
DerefMethod {
|
||||||
@ -744,7 +747,7 @@ fn in_postfix_position<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
enum TyCoercionStability {
|
enum TyCoercionStability {
|
||||||
Deref,
|
Deref,
|
||||||
Reborrow,
|
Reborrow,
|
||||||
@ -1042,16 +1045,28 @@ fn report<'tcx>(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (prefix, precedence) = if let Some(mutability) = mutability
|
let ty = typeck.expr_ty(expr);
|
||||||
&& !typeck.expr_ty(expr).is_ref()
|
|
||||||
|
// `&&[T; N]`, or `&&..&[T; N]` (src) cannot coerce to `&[T]` (dst).
|
||||||
|
if let ty::Ref(_, dst, _) = data.adjusted_ty.kind()
|
||||||
|
&& dst.is_slice()
|
||||||
{
|
{
|
||||||
let prefix = match mutability {
|
let (src, n_src_refs) = peel_middle_ty_refs(ty);
|
||||||
Mutability::Not => "&",
|
if n_src_refs >= 2 && src.is_array() {
|
||||||
Mutability::Mut => "&mut ",
|
return;
|
||||||
};
|
}
|
||||||
(prefix, PREC_PREFIX)
|
}
|
||||||
} else {
|
|
||||||
("", 0)
|
let (prefix, precedence) = match mutability {
|
||||||
|
Some(mutability) if !ty.is_ref() => {
|
||||||
|
let prefix = match mutability {
|
||||||
|
Mutability::Not => "&",
|
||||||
|
Mutability::Mut => "&mut ",
|
||||||
|
};
|
||||||
|
(prefix, PREC_PREFIX)
|
||||||
|
},
|
||||||
|
None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", 0),
|
||||||
|
_ => ("", 0),
|
||||||
};
|
};
|
||||||
span_lint_hir_and_then(
|
span_lint_hir_and_then(
|
||||||
cx,
|
cx,
|
||||||
|
@ -2492,6 +2492,17 @@ pub fn peel_hir_ty_refs<'a>(mut ty: &'a hir::Ty<'a>) -> (&'a hir::Ty<'a>, usize)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Peels off all references on the type. Returns the underlying type and the number of references
|
||||||
|
/// removed.
|
||||||
|
pub fn peel_middle_ty_refs(mut ty: Ty<'_>) -> (Ty<'_>, usize) {
|
||||||
|
let mut count = 0;
|
||||||
|
while let rustc_ty::Ref(_, dest_ty, _) = ty.kind() {
|
||||||
|
ty = *dest_ty;
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
(ty, count)
|
||||||
|
}
|
||||||
|
|
||||||
/// Removes `AddrOf` operators (`&`) or deref operators (`*`), but only if a reference type is
|
/// Removes `AddrOf` operators (`&`) or deref operators (`*`), but only if a reference type is
|
||||||
/// dereferenced. An overloaded deref such as `Vec` to slice would not be removed.
|
/// dereferenced. An overloaded deref such as `Vec` to slice would not be removed.
|
||||||
pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> {
|
pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> {
|
||||||
|
@ -345,3 +345,39 @@ fn main() {
|
|||||||
let _ = &mut ({ *x.u }).x;
|
let _ = &mut ({ *x.u }).x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod issue_12969 {
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
struct Wrapper<T>(T);
|
||||||
|
|
||||||
|
impl<T> Deref for Wrapper<T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo(_bar: &str) {}
|
||||||
|
|
||||||
|
fn bar() {
|
||||||
|
let wrapped_bar = Wrapper("");
|
||||||
|
|
||||||
|
foo(&wrapped_bar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod issue_9841 {
|
||||||
|
fn takes_array_ref<T, const N: usize>(array: &&[T; N]) {
|
||||||
|
takes_slice(*array)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn takes_array_ref_ref<T, const N: usize>(array: &&&[T; N]) {
|
||||||
|
takes_slice(**array)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn takes_slice<T>(slice: &[T]) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -345,3 +345,39 @@ struct S8 {
|
|||||||
let _ = &mut ({ *x.u }).x;
|
let _ = &mut ({ *x.u }).x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod issue_12969 {
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
struct Wrapper<T>(T);
|
||||||
|
|
||||||
|
impl<T> Deref for Wrapper<T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &T {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo(_bar: &str) {}
|
||||||
|
|
||||||
|
fn bar() {
|
||||||
|
let wrapped_bar = Wrapper("");
|
||||||
|
|
||||||
|
foo(&*wrapped_bar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod issue_9841 {
|
||||||
|
fn takes_array_ref<T, const N: usize>(array: &&[T; N]) {
|
||||||
|
takes_slice(*array)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn takes_array_ref_ref<T, const N: usize>(array: &&&[T; N]) {
|
||||||
|
takes_slice(**array)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn takes_slice<T>(slice: &[T]) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -271,5 +271,11 @@ error: deref which would be done by auto-deref
|
|||||||
LL | let _ = &mut (*{ x.u }).x;
|
LL | let _ = &mut (*{ x.u }).x;
|
||||||
| ^^^^^^^^^^ help: try: `{ x.u }`
|
| ^^^^^^^^^^ help: try: `{ x.u }`
|
||||||
|
|
||||||
error: aborting due to 45 previous errors
|
error: deref which would be done by auto-deref
|
||||||
|
--> tests/ui/explicit_auto_deref.rs:367:13
|
||||||
|
|
|
||||||
|
LL | foo(&*wrapped_bar);
|
||||||
|
| ^^^^^^^^^^^^^ help: try: `&wrapped_bar`
|
||||||
|
|
||||||
|
error: aborting due to 46 previous errors
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user