Rollup merge of #104742 - WaffleLapkin:forbidden-SUPER-deref, r=compiler-errors

Make `deref_into_dyn_supertrait` lint the impl and not the usage

Proposed by ``@compiler-errors`` in https://github.com/rust-lang/rust/issues/89460#issuecomment-1320806785
r? ``@crlf0710``
This commit is contained in:
Matthias Krüger 2022-11-24 08:42:34 +01:00 committed by GitHub
commit ac6a77ed95
4 changed files with 23 additions and 31 deletions

View File

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_opt; use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{get_associated_type, implements_trait, is_copy}; use clippy_utils::ty::{implements_trait, is_copy};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::Expr; use rustc_hir::Expr;
use rustc_lint::LateContext; use rustc_lint::LateContext;
@ -25,7 +25,7 @@ pub(super) fn check<'tcx>(
&& let Some(method_id) = typeck.type_dependent_def_id(cloned_call.hir_id) && let Some(method_id) = typeck.type_dependent_def_id(cloned_call.hir_id)
&& cx.tcx.trait_of_item(method_id) == Some(iter_id) && cx.tcx.trait_of_item(method_id) == Some(iter_id)
&& let cloned_recv_ty = typeck.expr_ty_adjusted(cloned_recv) && let cloned_recv_ty = typeck.expr_ty_adjusted(cloned_recv)
&& let Some(iter_assoc_ty) = get_associated_type(cx, cloned_recv_ty, iter_id, "Item") && let Some(iter_assoc_ty) = cx.get_associated_type(cloned_recv_ty, iter_id, "Item")
&& matches!(*iter_assoc_ty.kind(), ty::Ref(_, ty, _) if !is_copy(cx, ty)) && matches!(*iter_assoc_ty.kind(), ty::Ref(_, ty, _) if !is_copy(cx, ty))
{ {
if needs_into_iter if needs_into_iter

View File

@ -2,7 +2,7 @@ use super::utils::clone_or_copy_needed;
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::ForLoop; use clippy_utils::higher::ForLoop;
use clippy_utils::source::snippet_opt; use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait}; use clippy_utils::ty::{get_iterator_item_ty, implements_trait};
use clippy_utils::{fn_def_id, get_parent_expr}; use clippy_utils::{fn_def_id, get_parent_expr};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{def_id::DefId, Expr, ExprKind}; use rustc_hir::{def_id::DefId, Expr, ExprKind};
@ -54,7 +54,7 @@ pub fn check_for_loop_iter(
if let Some(into_iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator); if let Some(into_iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator);
let collection_ty = cx.typeck_results().expr_ty(collection); let collection_ty = cx.typeck_results().expr_ty(collection);
if implements_trait(cx, collection_ty, into_iterator_trait_id, &[]); if implements_trait(cx, collection_ty, into_iterator_trait_id, &[]);
if let Some(into_iter_item_ty) = get_associated_type(cx, collection_ty, into_iterator_trait_id, "Item"); if let Some(into_iter_item_ty) = cx.get_associated_type(collection_ty, into_iterator_trait_id, "Item");
if iter_item_ty == into_iter_item_ty; if iter_item_ty == into_iter_item_ty;
if let Some(collection_snippet) = snippet_opt(cx, collection.span); if let Some(collection_snippet) = snippet_opt(cx, collection.span);

View File

@ -2,9 +2,11 @@ use super::implicit_clone::is_clone_like;
use super::unnecessary_iter_cloned::{self, is_into_iter}; use super::unnecessary_iter_cloned::{self, is_into_iter};
use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_opt; use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs}; use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs};
use clippy_utils::visitors::find_all_ret_expressions; use clippy_utils::visitors::find_all_ret_expressions;
use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty}; use clippy_utils::{
fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty,
};
use clippy_utils::{meets_msrv, msrvs}; use clippy_utils::{meets_msrv, msrvs};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, Node}; use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, Node};
@ -18,7 +20,9 @@ use rustc_middle::ty::EarlyBinder;
use rustc_middle::ty::{self, ParamTy, PredicateKind, ProjectionPredicate, TraitPredicate, Ty}; use rustc_middle::ty::{self, ParamTy, PredicateKind, ProjectionPredicate, TraitPredicate, Ty};
use rustc_semver::RustcVersion; use rustc_semver::RustcVersion;
use rustc_span::{sym, Symbol}; use rustc_span::{sym, Symbol};
use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause}; use rustc_trait_selection::traits::{
query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause,
};
use std::cmp::max; use std::cmp::max;
use super::UNNECESSARY_TO_OWNED; use super::UNNECESSARY_TO_OWNED;
@ -146,7 +150,7 @@ fn check_addr_of_expr(
if_chain! { if_chain! {
if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref); if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref);
if implements_trait(cx, receiver_ty, deref_trait_id, &[]); if implements_trait(cx, receiver_ty, deref_trait_id, &[]);
if get_associated_type(cx, receiver_ty, deref_trait_id, "Target") == Some(target_ty); if cx.get_associated_type(receiver_ty, deref_trait_id, "Target") == Some(target_ty);
then { then {
if n_receiver_refs > 0 { if n_receiver_refs > 0 {
span_lint_and_sugg( span_lint_and_sugg(
@ -341,13 +345,13 @@ fn get_input_traits_and_projections<'tcx>(
if trait_predicate.trait_ref.self_ty() == input { if trait_predicate.trait_ref.self_ty() == input {
trait_predicates.push(trait_predicate); trait_predicates.push(trait_predicate);
} }
}, }
PredicateKind::Projection(projection_predicate) => { PredicateKind::Projection(projection_predicate) => {
if projection_predicate.projection_ty.self_ty() == input { if projection_predicate.projection_ty.self_ty() == input {
projection_predicates.push(projection_predicate); projection_predicates.push(projection_predicate);
} }
}, }
_ => {}, _ => {}
} }
} }
(trait_predicates, projection_predicates) (trait_predicates, projection_predicates)
@ -462,7 +466,12 @@ fn is_cloned_or_copied(cx: &LateContext<'_>, method_name: Symbol, method_def_id:
/// Returns true if the named method can be used to convert the receiver to its "owned" /// Returns true if the named method can be used to convert the receiver to its "owned"
/// representation. /// representation.
fn is_to_owned_like<'a>(cx: &LateContext<'a>, call_expr: &Expr<'a>, method_name: Symbol, method_def_id: DefId) -> bool { fn is_to_owned_like<'a>(
cx: &LateContext<'a>,
call_expr: &Expr<'a>,
method_name: Symbol,
method_def_id: DefId,
) -> bool {
is_clone_like(cx, method_name.as_str(), method_def_id) is_clone_like(cx, method_name.as_str(), method_def_id)
|| is_cow_into_owned(cx, method_name, method_def_id) || is_cow_into_owned(cx, method_name, method_def_id)
|| is_to_string_on_string_like(cx, call_expr, method_name, method_def_id) || is_to_string_on_string_like(cx, call_expr, method_name, method_def_id)
@ -490,7 +499,7 @@ fn is_to_string_on_string_like<'a>(
&& let GenericArgKind::Type(ty) = generic_arg.unpack() && let GenericArgKind::Type(ty) = generic_arg.unpack()
&& let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref) && let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref)
&& let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef) && let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef)
&& (get_associated_type(cx, ty, deref_trait_id, "Target") == Some(cx.tcx.types.str_) || && (cx.get_associated_type(ty, deref_trait_id, "Target") == Some(cx.tcx.types.str_) ||
implements_trait(cx, ty, as_ref_trait_id, &[cx.tcx.types.str_.into()])) { implements_trait(cx, ty, as_ref_trait_id, &[cx.tcx.types.str_.into()])) {
true true
} else { } else {

View File

@ -117,24 +117,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
pub fn get_iterator_item_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> { pub fn get_iterator_item_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
cx.tcx cx.tcx
.get_diagnostic_item(sym::Iterator) .get_diagnostic_item(sym::Iterator)
.and_then(|iter_did| get_associated_type(cx, ty, iter_did, "Item")) .and_then(|iter_did| cx.get_associated_type(ty, iter_did, "Item"))
}
/// Returns the associated type `name` for `ty` as an implementation of `trait_id`.
/// Do not invoke without first verifying that the type implements the trait.
pub fn get_associated_type<'tcx>(
cx: &LateContext<'tcx>,
ty: Ty<'tcx>,
trait_id: DefId,
name: &str,
) -> Option<Ty<'tcx>> {
cx.tcx
.associated_items(trait_id)
.find_by_name_and_kind(cx.tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id)
.and_then(|assoc| {
let proj = cx.tcx.mk_projection(assoc.def_id, cx.tcx.mk_substs_trait(ty, []));
cx.tcx.try_normalize_erasing_regions(cx.param_env, proj).ok()
})
} }
/// Get the diagnostic name of a type, e.g. `sym::HashMap`. To check if a type /// Get the diagnostic name of a type, e.g. `sym::HashMap`. To check if a type