mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-24 05:33:27 +00:00
Auto merge of #10010 - flip1995:rustup, r=flip1995
Rustup r? `@ghost` changelog: none
This commit is contained in:
commit
d822110d3b
39 changed files with 230 additions and 219 deletions
|
@ -6,7 +6,7 @@ use super::verify_inside_clippy_dir;
|
||||||
/// Rusts setup uses `git rev-parse --git-common-dir` to get the root directory of the repo.
|
/// Rusts setup uses `git rev-parse --git-common-dir` to get the root directory of the repo.
|
||||||
/// I've decided against this for the sake of simplicity and to make sure that it doesn't install
|
/// I've decided against this for the sake of simplicity and to make sure that it doesn't install
|
||||||
/// the hook if `clippy_dev` would be used in the rust tree. The hook also references this tool
|
/// the hook if `clippy_dev` would be used in the rust tree. The hook also references this tool
|
||||||
/// for formatting and should therefor only be used in a normal clone of clippy
|
/// for formatting and should therefore only be used in a normal clone of clippy
|
||||||
const REPO_GIT_DIR: &str = ".git";
|
const REPO_GIT_DIR: &str = ".git";
|
||||||
const HOOK_SOURCE_FILE: &str = "util/etc/pre-commit.sh";
|
const HOOK_SOURCE_FILE: &str = "util/etc/pre-commit.sh";
|
||||||
const HOOK_TARGET_FILE: &str = ".git/hooks/pre-commit";
|
const HOOK_TARGET_FILE: &str = ".git/hooks/pre-commit";
|
||||||
|
|
|
@ -5,7 +5,7 @@ use clippy_utils::macros::{is_panic, macro_backtrace};
|
||||||
use clippy_utils::msrvs::{self, Msrv};
|
use clippy_utils::msrvs::{self, Msrv};
|
||||||
use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments};
|
use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
|
use rustc_ast::{AttrKind, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind,
|
Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind,
|
||||||
|
@ -574,7 +574,7 @@ fn check_attrs(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Attribut
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_semver(cx: &LateContext<'_>, span: Span, lit: &Lit) {
|
fn check_semver(cx: &LateContext<'_>, span: Span, lit: &MetaItemLit) {
|
||||||
if let LitKind::Str(is, _) = lit.kind {
|
if let LitKind::Str(is, _) = lit.kind {
|
||||||
if Version::parse(is.as_str()).is_ok() {
|
if Version::parse(is.as_str()).is_ok() {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -59,7 +59,7 @@ fn is_impl_not_trait_with_bool_out(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.map_or(false, |assoc_item| {
|
.map_or(false, |assoc_item| {
|
||||||
let proj = cx.tcx.mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(ty, &[]));
|
let proj = cx.tcx.mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(ty, []));
|
||||||
let nty = cx.tcx.normalize_erasing_regions(cx.param_env, proj);
|
let nty = cx.tcx.normalize_erasing_regions(cx.param_env, proj);
|
||||||
|
|
||||||
nty.is_bool()
|
nty.is_bool()
|
||||||
|
|
|
@ -2,12 +2,11 @@ use clippy_utils::consts::{constant, Constant};
|
||||||
use clippy_utils::diagnostics::span_lint;
|
use clippy_utils::diagnostics::span_lint;
|
||||||
use clippy_utils::expr_or_init;
|
use clippy_utils::expr_or_init;
|
||||||
use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize};
|
use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize};
|
||||||
use rustc_ast::ast;
|
|
||||||
use rustc_attr::IntType;
|
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::{BinOpKind, Expr, ExprKind};
|
use rustc_hir::{BinOpKind, Expr, ExprKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::ty::{self, FloatTy, Ty};
|
use rustc_middle::ty::{self, FloatTy, Ty};
|
||||||
|
use rustc_target::abi::IntegerType;
|
||||||
|
|
||||||
use super::{utils, CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION};
|
use super::{utils, CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION};
|
||||||
|
|
||||||
|
@ -119,12 +118,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
|
||||||
};
|
};
|
||||||
let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);
|
let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);
|
||||||
|
|
||||||
let cast_from_ptr_size = def.repr().int.map_or(true, |ty| {
|
let cast_from_ptr_size = def.repr().int.map_or(true, |ty| matches!(ty, IntegerType::Pointer(_),));
|
||||||
matches!(
|
|
||||||
ty,
|
|
||||||
IntType::SignedInt(ast::IntTy::Isize) | IntType::UnsignedInt(ast::UintTy::Usize)
|
|
||||||
)
|
|
||||||
});
|
|
||||||
let suffix = match (cast_from_ptr_size, is_isize_or_usize(cast_to)) {
|
let suffix = match (cast_from_ptr_size, is_isize_or_usize(cast_to)) {
|
||||||
(false, false) if from_nbits > to_nbits => "",
|
(false, false) if from_nbits > to_nbits => "",
|
||||||
(true, false) if from_nbits > to_nbits => "",
|
(true, false) if from_nbits > to_nbits => "",
|
||||||
|
|
|
@ -55,7 +55,7 @@ impl EarlyLintPass for CrateInMacroDef {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if item.attrs.iter().any(is_macro_export);
|
if item.attrs.iter().any(is_macro_export);
|
||||||
if let ItemKind::MacroDef(macro_def) = &item.kind;
|
if let ItemKind::MacroDef(macro_def) = &item.kind;
|
||||||
let tts = macro_def.body.inner_tokens();
|
let tts = macro_def.body.tokens.clone();
|
||||||
if let Some(span) = contains_unhygienic_crate_reference(&tts);
|
if let Some(span) = contains_unhygienic_crate_reference(&tts);
|
||||||
then {
|
then {
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
|
|
|
@ -26,7 +26,7 @@ use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::mir::{Rvalue, StatementKind};
|
use rustc_middle::mir::{Rvalue, StatementKind};
|
||||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
|
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, Binder, BoundVariableKind, EarlyBinder, FnSig, GenericArgKind, List, ParamTy, PredicateKind,
|
self, Binder, BoundVariableKind, Clause, EarlyBinder, FnSig, GenericArgKind, List, ParamTy, PredicateKind,
|
||||||
ProjectionPredicate, Ty, TyCtxt, TypeVisitable, TypeckResults,
|
ProjectionPredicate, Ty, TyCtxt, TypeVisitable, TypeckResults,
|
||||||
};
|
};
|
||||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||||
|
@ -855,14 +855,10 @@ fn walk_parents<'tcx>(
|
||||||
} else if let Some(trait_id) = cx.tcx.trait_of_item(id)
|
} else if let Some(trait_id) = cx.tcx.trait_of_item(id)
|
||||||
&& let arg_ty = cx.tcx.erase_regions(cx.typeck_results().expr_ty_adjusted(e))
|
&& let arg_ty = cx.tcx.erase_regions(cx.typeck_results().expr_ty_adjusted(e))
|
||||||
&& let ty::Ref(_, sub_ty, _) = *arg_ty.kind()
|
&& let ty::Ref(_, sub_ty, _) = *arg_ty.kind()
|
||||||
&& let subs = match cx
|
&& let subs = cx
|
||||||
.typeck_results()
|
.typeck_results()
|
||||||
.node_substs_opt(parent.hir_id)
|
.node_substs_opt(parent.hir_id).map(|subs| &subs[1..]).unwrap_or_default()
|
||||||
.and_then(|subs| subs.get(1..))
|
&& let impl_ty = if cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref() {
|
||||||
{
|
|
||||||
Some(subs) => cx.tcx.mk_substs(subs.iter().copied()),
|
|
||||||
None => cx.tcx.mk_substs(std::iter::empty::<ty::subst::GenericArg<'_>>()),
|
|
||||||
} && let impl_ty = if cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref() {
|
|
||||||
// Trait methods taking `&self`
|
// Trait methods taking `&self`
|
||||||
sub_ty
|
sub_ty
|
||||||
} else {
|
} else {
|
||||||
|
@ -871,7 +867,11 @@ fn walk_parents<'tcx>(
|
||||||
} && impl_ty.is_ref()
|
} && impl_ty.is_ref()
|
||||||
&& let infcx = cx.tcx.infer_ctxt().build()
|
&& let infcx = cx.tcx.infer_ctxt().build()
|
||||||
&& infcx
|
&& infcx
|
||||||
.type_implements_trait(trait_id, impl_ty, subs, cx.param_env)
|
.type_implements_trait(
|
||||||
|
trait_id,
|
||||||
|
[impl_ty.into()].into_iter().chain(subs.iter().copied()),
|
||||||
|
cx.param_env,
|
||||||
|
)
|
||||||
.must_apply_modulo_regions()
|
.must_apply_modulo_regions()
|
||||||
{
|
{
|
||||||
return Some(Position::MethodReceiverRefImpl)
|
return Some(Position::MethodReceiverRefImpl)
|
||||||
|
@ -1106,7 +1106,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
|
||||||
let projection_predicates = predicates
|
let projection_predicates = predicates
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|predicate| {
|
.filter_map(|predicate| {
|
||||||
if let PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() {
|
if let PredicateKind::Clause(Clause::Projection(projection_predicate)) = predicate.kind().skip_binder() {
|
||||||
Some(projection_predicate)
|
Some(projection_predicate)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -1120,7 +1120,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
|
||||||
if predicates
|
if predicates
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|predicate| {
|
.filter_map(|predicate| {
|
||||||
if let PredicateKind::Trait(trait_predicate) = predicate.kind().skip_binder()
|
if let PredicateKind::Clause(Clause::Trait(trait_predicate)) = predicate.kind().skip_binder()
|
||||||
&& trait_predicate.trait_ref.self_ty() == param_ty.to_ty(cx.tcx)
|
&& trait_predicate.trait_ref.self_ty() == param_ty.to_ty(cx.tcx)
|
||||||
{
|
{
|
||||||
Some(trait_predicate.trait_ref.def_id)
|
Some(trait_predicate.trait_ref.def_id)
|
||||||
|
@ -1182,7 +1182,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
predicates.iter().all(|predicate| {
|
predicates.iter().all(|predicate| {
|
||||||
if let PredicateKind::Trait(trait_predicate) = predicate.kind().skip_binder()
|
if let PredicateKind::Clause(Clause::Trait(trait_predicate)) = predicate.kind().skip_binder()
|
||||||
&& cx.tcx.is_diagnostic_item(sym::IntoIterator, trait_predicate.trait_ref.def_id)
|
&& cx.tcx.is_diagnostic_item(sym::IntoIterator, trait_predicate.trait_ref.def_id)
|
||||||
&& let ty::Param(param_ty) = trait_predicate.self_ty().kind()
|
&& let ty::Param(param_ty) = trait_predicate.self_ty().kind()
|
||||||
&& let GenericArgKind::Type(ty) = substs_with_referent_ty[param_ty.index as usize].unpack()
|
&& let GenericArgKind::Type(ty) = substs_with_referent_ty[param_ty.index as usize].unpack()
|
||||||
|
@ -1333,7 +1333,7 @@ fn replace_types<'tcx>(
|
||||||
let item_def_id = projection_predicate.projection_ty.item_def_id;
|
let item_def_id = projection_predicate.projection_ty.item_def_id;
|
||||||
let assoc_item = cx.tcx.associated_item(item_def_id);
|
let assoc_item = cx.tcx.associated_item(item_def_id);
|
||||||
let projection = cx.tcx
|
let projection = cx.tcx
|
||||||
.mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(new_ty, &[]));
|
.mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(new_ty, []));
|
||||||
|
|
||||||
if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection)
|
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)
|
&& substs[term_param_ty.index as usize] != ty::GenericArg::from(projected_ty)
|
||||||
|
|
|
@ -14,8 +14,8 @@ use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::traits::Reveal;
|
use rustc_middle::traits::Reveal;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, Binder, BoundConstness, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind, TraitPredicate, TraitRef,
|
self, Binder, BoundConstness, Clause, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind, TraitPredicate,
|
||||||
Ty, TyCtxt,
|
TraitRef, Ty, TyCtxt,
|
||||||
};
|
};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::source_map::Span;
|
use rustc_span::source_map::Span;
|
||||||
|
@ -466,12 +466,12 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r
|
||||||
if let Some(def_id) = trait_ref.trait_def_id();
|
if let Some(def_id) = trait_ref.trait_def_id();
|
||||||
if cx.tcx.is_diagnostic_item(sym::PartialEq, def_id);
|
if cx.tcx.is_diagnostic_item(sym::PartialEq, def_id);
|
||||||
let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id);
|
let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id);
|
||||||
if !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, &[]);
|
if !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, []);
|
||||||
// If all of our fields implement `Eq`, we can implement `Eq` too
|
// If all of our fields implement `Eq`, we can implement `Eq` too
|
||||||
if adt
|
if adt
|
||||||
.all_fields()
|
.all_fields()
|
||||||
.map(|f| f.ty(cx.tcx, substs))
|
.map(|f| f.ty(cx.tcx, substs))
|
||||||
.all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, &[]));
|
.all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, []));
|
||||||
then {
|
then {
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
|
@ -499,7 +499,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
|
||||||
|
|
||||||
let ty_predicates = tcx.predicates_of(did).predicates;
|
let ty_predicates = tcx.predicates_of(did).predicates;
|
||||||
for (p, _) in ty_predicates {
|
for (p, _) in ty_predicates {
|
||||||
if let PredicateKind::Trait(p) = p.kind().skip_binder()
|
if let PredicateKind::Clause(Clause::Trait(p)) = p.kind().skip_binder()
|
||||||
&& p.trait_ref.def_id == eq_trait_id
|
&& p.trait_ref.def_id == eq_trait_id
|
||||||
&& let ty::Param(self_ty) = p.trait_ref.self_ty().kind()
|
&& let ty::Param(self_ty) = p.trait_ref.self_ty().kind()
|
||||||
&& p.constness == BoundConstness::NotConst
|
&& p.constness == BoundConstness::NotConst
|
||||||
|
@ -512,14 +512,14 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
|
||||||
ParamEnv::new(
|
ParamEnv::new(
|
||||||
tcx.mk_predicates(ty_predicates.iter().map(|&(p, _)| p).chain(
|
tcx.mk_predicates(ty_predicates.iter().map(|&(p, _)| p).chain(
|
||||||
params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| {
|
params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| {
|
||||||
tcx.mk_predicate(Binder::dummy(PredicateKind::Trait(TraitPredicate {
|
tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(Clause::Trait(TraitPredicate {
|
||||||
trait_ref: TraitRef::new(
|
trait_ref: TraitRef::new(
|
||||||
eq_trait_id,
|
eq_trait_id,
|
||||||
tcx.mk_substs(std::iter::once(tcx.mk_param_from_def(param))),
|
tcx.mk_substs(std::iter::once(tcx.mk_param_from_def(param))),
|
||||||
),
|
),
|
||||||
constness: BoundConstness::NotConst,
|
constness: BoundConstness::NotConst,
|
||||||
polarity: ImplPolarity::Positive,
|
polarity: ImplPolarity::Positive,
|
||||||
})))
|
}))))
|
||||||
}),
|
}),
|
||||||
)),
|
)),
|
||||||
Reveal::UserFacing,
|
Reveal::UserFacing,
|
||||||
|
|
|
@ -427,9 +427,7 @@ fn lint_for_missing_headers(
|
||||||
let body = cx.tcx.hir().body(body_id);
|
let body = cx.tcx.hir().body(body_id);
|
||||||
let ret_ty = typeck.expr_ty(body.value);
|
let ret_ty = typeck.expr_ty(body.value);
|
||||||
if implements_trait(cx, ret_ty, future, &[]);
|
if implements_trait(cx, ret_ty, future, &[]);
|
||||||
if let ty::Opaque(_, subs) = ret_ty.kind();
|
if let ty::Generator(_, subs, _) = ret_ty.kind();
|
||||||
if let Some(gen) = subs.types().next();
|
|
||||||
if let ty::Generator(_, subs, _) = gen.kind();
|
|
||||||
if is_type_diagnostic_item(cx, subs.as_generator().return_ty(), sym::Result);
|
if is_type_diagnostic_item(cx, subs.as_generator().return_ty(), sym::Result);
|
||||||
then {
|
then {
|
||||||
span_lint(
|
span_lint(
|
||||||
|
|
|
@ -119,11 +119,18 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
|
||||||
let callee_ty_unadjusted = cx.typeck_results().expr_ty(callee).peel_refs();
|
let callee_ty_unadjusted = cx.typeck_results().expr_ty(callee).peel_refs();
|
||||||
if !is_type_diagnostic_item(cx, callee_ty_unadjusted, sym::Arc);
|
if !is_type_diagnostic_item(cx, callee_ty_unadjusted, sym::Arc);
|
||||||
if !is_type_diagnostic_item(cx, callee_ty_unadjusted, sym::Rc);
|
if !is_type_diagnostic_item(cx, callee_ty_unadjusted, sym::Rc);
|
||||||
|
if let ty::Closure(_, substs) = *closure_ty.kind();
|
||||||
then {
|
then {
|
||||||
span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| {
|
span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| {
|
||||||
if let Some(mut snippet) = snippet_opt(cx, callee.span) {
|
if let Some(mut snippet) = snippet_opt(cx, callee.span) {
|
||||||
if let Some(fn_mut_id) = cx.tcx.lang_items().fn_mut_trait()
|
if let Some(fn_mut_id) = cx.tcx.lang_items().fn_mut_trait()
|
||||||
&& implements_trait(cx, callee_ty.peel_refs(), fn_mut_id, &[])
|
&& let args = cx.tcx.erase_late_bound_regions(substs.as_closure().sig()).inputs()
|
||||||
|
&& implements_trait(
|
||||||
|
cx,
|
||||||
|
callee_ty.peel_refs(),
|
||||||
|
fn_mut_id,
|
||||||
|
&args.iter().copied().map(Into::into).collect::<Vec<_>>(),
|
||||||
|
)
|
||||||
&& path_to_local(callee).map_or(false, |l| local_used_after_expr(cx, l, expr))
|
&& path_to_local(callee).map_or(false, |l| local_used_after_expr(cx, l, expr))
|
||||||
{
|
{
|
||||||
// Mutable closure is used after current expr; we cannot consume it.
|
// Mutable closure is used after current expr; we cannot consume it.
|
||||||
|
|
|
@ -4,7 +4,7 @@ use rustc_hir::intravisit::FnKind;
|
||||||
use rustc_hir::{Body, FnDecl, HirId};
|
use rustc_hir::{Body, FnDecl, HirId};
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty::{EarlyBinder, Opaque, PredicateKind::Trait};
|
use rustc_middle::ty::{Clause, EarlyBinder, Opaque, PredicateKind};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::{sym, Span};
|
use rustc_span::{sym, Span};
|
||||||
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
|
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
|
||||||
|
@ -91,7 +91,9 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
|
||||||
infcx
|
infcx
|
||||||
.err_ctxt()
|
.err_ctxt()
|
||||||
.maybe_note_obligation_cause_for_async_await(db, &obligation);
|
.maybe_note_obligation_cause_for_async_await(db, &obligation);
|
||||||
if let Trait(trait_pred) = obligation.predicate.kind().skip_binder() {
|
if let PredicateKind::Clause(Clause::Trait(trait_pred)) =
|
||||||
|
obligation.predicate.kind().skip_binder()
|
||||||
|
{
|
||||||
db.note(&format!(
|
db.note(&format!(
|
||||||
"`{}` doesn't implement `{}`",
|
"`{}` doesn't implement `{}`",
|
||||||
trait_pred.self_ty(),
|
trait_pred.self_ty(),
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
extern crate rustc_arena;
|
extern crate rustc_arena;
|
||||||
extern crate rustc_ast;
|
extern crate rustc_ast;
|
||||||
extern crate rustc_ast_pretty;
|
extern crate rustc_ast_pretty;
|
||||||
extern crate rustc_attr;
|
|
||||||
extern crate rustc_data_structures;
|
extern crate rustc_data_structures;
|
||||||
extern crate rustc_driver;
|
extern crate rustc_driver;
|
||||||
extern crate rustc_errors;
|
extern crate rustc_errors;
|
||||||
|
|
|
@ -10,8 +10,8 @@ use rustc_hir::lang_items;
|
||||||
use rustc_hir::FnRetTy::Return;
|
use rustc_hir::FnRetTy::Return;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
|
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
|
||||||
ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin, TraitFn, TraitItem,
|
ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, PolyTraitRef, PredicateOrigin, TraitFn,
|
||||||
TraitItemKind, Ty, TyKind, WherePredicate,
|
TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::hir::nested_filter as middle_nested_filter;
|
use rustc_middle::hir::nested_filter as middle_nested_filter;
|
||||||
|
@ -180,7 +180,7 @@ fn check_fn_inner<'tcx>(
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
for bound in lifetimes {
|
for bound in lifetimes {
|
||||||
if bound.name != LifetimeName::Static && !bound.is_elided() {
|
if !bound.is_static() && !bound.is_elided() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -414,17 +414,13 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
|
||||||
|
|
||||||
fn record(&mut self, lifetime: &Option<Lifetime>) {
|
fn record(&mut self, lifetime: &Option<Lifetime>) {
|
||||||
if let Some(ref lt) = *lifetime {
|
if let Some(ref lt) = *lifetime {
|
||||||
if lt.name == LifetimeName::Static {
|
if lt.is_static() {
|
||||||
self.lts.push(RefLt::Static);
|
self.lts.push(RefLt::Static);
|
||||||
} else if let LifetimeName::Param(_, ParamName::Fresh) = lt.name {
|
} else if lt.is_anonymous() {
|
||||||
// Fresh lifetimes generated should be ignored.
|
// Fresh lifetimes generated should be ignored.
|
||||||
self.lts.push(RefLt::Unnamed);
|
self.lts.push(RefLt::Unnamed);
|
||||||
} else if lt.is_elided() {
|
} else if let LifetimeName::Param(def_id) = lt.res {
|
||||||
self.lts.push(RefLt::Unnamed);
|
|
||||||
} else if let LifetimeName::Param(def_id, _) = lt.name {
|
|
||||||
self.lts.push(RefLt::Named(def_id));
|
self.lts.push(RefLt::Named(def_id));
|
||||||
} else {
|
|
||||||
self.lts.push(RefLt::Unnamed);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.lts.push(RefLt::Unnamed);
|
self.lts.push(RefLt::Unnamed);
|
||||||
|
@ -472,7 +468,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
|
||||||
walk_item(self, item);
|
walk_item(self, item);
|
||||||
self.lts.truncate(len);
|
self.lts.truncate(len);
|
||||||
self.lts.extend(bounds.iter().filter_map(|bound| match bound {
|
self.lts.extend(bounds.iter().filter_map(|bound| match bound {
|
||||||
GenericArg::Lifetime(l) => Some(if let LifetimeName::Param(def_id, _) = l.name {
|
GenericArg::Lifetime(l) => Some(if let LifetimeName::Param(def_id) = l.res {
|
||||||
RefLt::Named(def_id)
|
RefLt::Named(def_id)
|
||||||
} else {
|
} else {
|
||||||
RefLt::Unnamed
|
RefLt::Unnamed
|
||||||
|
@ -498,10 +494,8 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_generic_arg(&mut self, generic_arg: &'tcx GenericArg<'tcx>) {
|
fn visit_generic_arg(&mut self, generic_arg: &'tcx GenericArg<'tcx>) {
|
||||||
if let GenericArg::Lifetime(l) = generic_arg
|
if let GenericArg::Lifetime(l) = generic_arg && let LifetimeName::Param(def_id) = l.res {
|
||||||
&& let LifetimeName::Param(def_id, _) = l.name
|
self.lifetime_generic_arg_spans.entry(def_id).or_insert(l.ident.span);
|
||||||
{
|
|
||||||
self.lifetime_generic_arg_spans.entry(def_id).or_insert(l.span);
|
|
||||||
}
|
}
|
||||||
walk_generic_arg(self, generic_arg);
|
walk_generic_arg(self, generic_arg);
|
||||||
}
|
}
|
||||||
|
@ -570,7 +564,7 @@ where
|
||||||
|
|
||||||
// for lifetimes as parameters of generics
|
// for lifetimes as parameters of generics
|
||||||
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
|
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
|
||||||
self.map.remove(&lifetime.name.ident().name);
|
self.map.remove(&lifetime.ident.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_generic_param(&mut self, param: &'tcx GenericParam<'_>) {
|
fn visit_generic_param(&mut self, param: &'tcx GenericParam<'_>) {
|
||||||
|
@ -594,7 +588,9 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>,
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|par| match par.kind {
|
.filter_map(|par| match par.kind {
|
||||||
GenericParamKind::Lifetime { .. } => Some((par.name.ident().name, par.span)),
|
GenericParamKind::Lifetime {
|
||||||
|
kind: LifetimeParamKind::Explicit,
|
||||||
|
} => Some((par.name.ident().name, par.span)),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -619,7 +615,9 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|par| match par.kind {
|
.filter_map(|par| match par.kind {
|
||||||
GenericParamKind::Lifetime { .. } => Some((par.name.ident().name, par.span)),
|
GenericParamKind::Lifetime {
|
||||||
|
kind: LifetimeParamKind::Explicit,
|
||||||
|
} => Some((par.name.ident().name, par.span)),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -646,7 +644,7 @@ struct BodyLifetimeChecker {
|
||||||
impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker {
|
impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker {
|
||||||
// for lifetimes as parameters of generics
|
// for lifetimes as parameters of generics
|
||||||
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
|
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
|
||||||
if lifetime.name.ident().name != kw::UnderscoreLifetime && lifetime.name.ident().name != kw::StaticLifetime {
|
if !lifetime.is_anonymous() && lifetime.ident.name != kw::StaticLifetime {
|
||||||
self.lifetimes_used_in_body = true;
|
self.lifetimes_used_in_body = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ fn future_trait_ref<'tcx>(
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|bound| {
|
.filter_map(|bound| {
|
||||||
if let GenericArg::Lifetime(lt) = bound {
|
if let GenericArg::Lifetime(lt) = bound {
|
||||||
Some(lt.name)
|
Some(lt.res)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName])
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|ty| {
|
.filter_map(|ty| {
|
||||||
if let TyKind::Rptr(lt, _) = ty.kind {
|
if let TyKind::Rptr(lt, _) = ty.kind {
|
||||||
Some(lt.name)
|
Some(lt.res)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -177,7 +177,7 @@ fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>)
|
||||||
if let Some(args) = cx
|
if let Some(args) = cx
|
||||||
.tcx
|
.tcx
|
||||||
.lang_items()
|
.lang_items()
|
||||||
.from_generator_fn()
|
.identity_future_fn()
|
||||||
.and_then(|def_id| match_function_call_with_def_id(cx, block_expr, def_id));
|
.and_then(|def_id| match_function_call_with_def_id(cx, block_expr, def_id));
|
||||||
if args.len() == 1;
|
if args.len() == 1;
|
||||||
if let Expr {
|
if let Expr {
|
||||||
|
|
|
@ -65,14 +65,14 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
if arm.guard.is_none() {
|
if arm.guard.is_none() {
|
||||||
missing_variants.retain(|e| e.ctor_def_id != Some(id));
|
missing_variants.retain(|e| e.ctor_def_id() != Some(id));
|
||||||
}
|
}
|
||||||
path
|
path
|
||||||
},
|
},
|
||||||
PatKind::TupleStruct(path, patterns, ..) => {
|
PatKind::TupleStruct(path, patterns, ..) => {
|
||||||
if let Some(id) = cx.qpath_res(path, pat.hir_id).opt_def_id() {
|
if let Some(id) = cx.qpath_res(path, pat.hir_id).opt_def_id() {
|
||||||
if arm.guard.is_none() && patterns.iter().all(|p| !is_refutable(cx, p)) {
|
if arm.guard.is_none() && patterns.iter().all(|p| !is_refutable(cx, p)) {
|
||||||
missing_variants.retain(|e| e.ctor_def_id != Some(id));
|
missing_variants.retain(|e| e.ctor_def_id() != Some(id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
path
|
path
|
||||||
|
@ -122,11 +122,11 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
|
||||||
s
|
s
|
||||||
},
|
},
|
||||||
variant.name,
|
variant.name,
|
||||||
match variant.ctor_kind {
|
match variant.ctor_kind() {
|
||||||
CtorKind::Fn if variant.fields.len() == 1 => "(_)",
|
Some(CtorKind::Fn) if variant.fields.len() == 1 => "(_)",
|
||||||
CtorKind::Fn => "(..)",
|
Some(CtorKind::Fn) => "(..)",
|
||||||
CtorKind::Const => "",
|
Some(CtorKind::Const) => "",
|
||||||
CtorKind::Fictive => "{ .. }",
|
None => "{ .. }",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::snippet_with_applicability;
|
use clippy_utils::source::snippet_with_applicability;
|
||||||
use clippy_utils::ty::is_type_diagnostic_item;
|
use clippy_utils::ty::is_type_diagnostic_item;
|
||||||
use clippy_utils::{get_parent_expr, is_res_lang_ctor, match_def_path, path_res, paths};
|
use clippy_utils::{get_parent_expr, is_res_lang_ctor, path_res};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::LangItem::ResultErr;
|
use rustc_hir::LangItem::ResultErr;
|
||||||
|
@ -107,7 +107,7 @@ fn result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'t
|
||||||
fn poll_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
|
fn poll_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let ty::Adt(def, subst) = ty.kind();
|
if let ty::Adt(def, subst) = ty.kind();
|
||||||
if match_def_path(cx, def.did(), &paths::POLL);
|
if cx.tcx.lang_items().get(LangItem::Poll) == Some(def.did());
|
||||||
let ready_ty = subst.type_at(0);
|
let ready_ty = subst.type_at(0);
|
||||||
|
|
||||||
if let ty::Adt(ready_def, ready_subst) = ready_ty.kind();
|
if let ty::Adt(ready_def, ready_subst) = ready_ty.kind();
|
||||||
|
@ -124,7 +124,7 @@ fn poll_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<
|
||||||
fn poll_option_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
|
fn poll_option_result_error_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let ty::Adt(def, subst) = ty.kind();
|
if let ty::Adt(def, subst) = ty.kind();
|
||||||
if match_def_path(cx, def.did(), &paths::POLL);
|
if cx.tcx.lang_items().get(LangItem::Poll) == Some(def.did());
|
||||||
let ready_ty = subst.type_at(0);
|
let ready_ty = subst.type_at(0);
|
||||||
|
|
||||||
if let ty::Adt(ready_def, ready_subst) = ready_ty.kind();
|
if let ty::Adt(ready_def, ready_subst) = ready_ty.kind();
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -3,7 +3,7 @@ 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::msrvs::{self, Msrv};
|
use clippy_utils::msrvs::{self, Msrv};
|
||||||
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 rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
|
@ -14,8 +14,7 @@ use rustc_lint::LateContext;
|
||||||
use rustc_middle::mir::Mutability;
|
use rustc_middle::mir::Mutability;
|
||||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
|
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
|
||||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
|
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
|
||||||
use rustc_middle::ty::EarlyBinder;
|
use rustc_middle::ty::{self, Clause, EarlyBinder, ParamTy, PredicateKind, ProjectionPredicate, TraitPredicate, Ty};
|
||||||
use rustc_middle::ty::{self, ParamTy, PredicateKind, ProjectionPredicate, TraitPredicate, Ty};
|
|
||||||
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};
|
||||||
|
|
||||||
|
@ -144,7 +143,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(
|
||||||
|
@ -346,12 +345,12 @@ fn get_input_traits_and_projections<'tcx>(
|
||||||
let mut projection_predicates = Vec::new();
|
let mut projection_predicates = Vec::new();
|
||||||
for predicate in cx.tcx.param_env(callee_def_id).caller_bounds() {
|
for predicate in cx.tcx.param_env(callee_def_id).caller_bounds() {
|
||||||
match predicate.kind().skip_binder() {
|
match predicate.kind().skip_binder() {
|
||||||
PredicateKind::Trait(trait_predicate) => {
|
PredicateKind::Clause(Clause::Trait(trait_predicate)) => {
|
||||||
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::Clause(Clause::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);
|
||||||
}
|
}
|
||||||
|
@ -408,10 +407,12 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
|
||||||
|
|
||||||
let mut trait_predicates = cx.tcx.param_env(callee_def_id)
|
let mut trait_predicates = cx.tcx.param_env(callee_def_id)
|
||||||
.caller_bounds().iter().filter(|predicate| {
|
.caller_bounds().iter().filter(|predicate| {
|
||||||
if let PredicateKind::Trait(trait_predicate) = predicate.kind().skip_binder()
|
if let PredicateKind::Clause(Clause::Trait(trait_predicate))
|
||||||
&& trait_predicate.trait_ref.self_ty() == *param_ty {
|
= predicate.kind().skip_binder()
|
||||||
true
|
&& trait_predicate.trait_ref.self_ty() == *param_ty
|
||||||
} else {
|
{
|
||||||
|
true
|
||||||
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -483,7 +484,7 @@ fn is_cow_into_owned(cx: &LateContext<'_>, method_name: Symbol, method_def_id: D
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the named method is `ToString::to_string` and it's called on a type that
|
/// Returns true if the named method is `ToString::to_string` and it's called on a type that
|
||||||
/// is string-like i.e. implements `AsRef<str>` or `Deref<str>`.
|
/// is string-like i.e. implements `AsRef<str>` or `Deref<Target = str>`.
|
||||||
fn is_to_string_on_string_like<'a>(
|
fn is_to_string_on_string_like<'a>(
|
||||||
cx: &LateContext<'_>,
|
cx: &LateContext<'_>,
|
||||||
call_expr: &'a Expr<'a>,
|
call_expr: &'a Expr<'a>,
|
||||||
|
@ -499,7 +500,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)
|
||||||
&& (implements_trait(cx, ty, deref_trait_id, &[cx.tcx.types.str_.into()]) ||
|
&& (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 {
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
|
use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
|
||||||
use clippy_utils::ptr::get_spans;
|
use clippy_utils::ptr::get_spans;
|
||||||
use clippy_utils::source::{snippet, snippet_opt};
|
use clippy_utils::source::{snippet, snippet_opt};
|
||||||
use clippy_utils::ty::{implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item};
|
use clippy_utils::ty::{
|
||||||
|
implements_trait, implements_trait_with_env, is_copy, is_type_diagnostic_item, is_type_lang_item,
|
||||||
|
};
|
||||||
use clippy_utils::{get_trait_def_id, is_self, paths};
|
use clippy_utils::{get_trait_def_id, is_self, paths};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_ast::ast::Attribute;
|
use rustc_ast::ast::Attribute;
|
||||||
|
@ -124,7 +126,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
|
||||||
.filter_map(|obligation| {
|
.filter_map(|obligation| {
|
||||||
// Note that we do not want to deal with qualified predicates here.
|
// Note that we do not want to deal with qualified predicates here.
|
||||||
match obligation.predicate.kind().no_bound_vars() {
|
match obligation.predicate.kind().no_bound_vars() {
|
||||||
Some(ty::PredicateKind::Trait(pred)) if pred.def_id() != sized_trait => Some(pred),
|
Some(ty::PredicateKind::Clause(ty::Clause::Trait(pred))) if pred.def_id() != sized_trait => {
|
||||||
|
Some(pred)
|
||||||
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -185,7 +189,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
|
||||||
if !ty.is_mutable_ptr();
|
if !ty.is_mutable_ptr();
|
||||||
if !is_copy(cx, ty);
|
if !is_copy(cx, ty);
|
||||||
if ty.is_sized(cx.tcx, cx.param_env);
|
if ty.is_sized(cx.tcx, cx.param_env);
|
||||||
if !allowed_traits.iter().any(|&t| implements_trait(cx, ty, t, &[]));
|
if !allowed_traits.iter().any(|&t| implements_trait_with_env(cx.tcx, cx.param_env, ty, t, [None]));
|
||||||
if !implements_borrow_trait;
|
if !implements_borrow_trait;
|
||||||
if !all_borrowable_trait;
|
if !all_borrowable_trait;
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd {
|
||||||
|
|
||||||
let implements_partial_ord = {
|
let implements_partial_ord = {
|
||||||
if let Some(id) = cx.tcx.lang_items().partial_ord_trait() {
|
if let Some(id) = cx.tcx.lang_items().partial_ord_trait() {
|
||||||
implements_trait(cx, ty, id, &[])
|
implements_trait(cx, ty, id, &[ty.into()])
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,14 +12,14 @@ use rustc_hir::hir_id::HirIdMap;
|
||||||
use rustc_hir::intravisit::{walk_expr, Visitor};
|
use rustc_hir::intravisit::{walk_expr, Visitor};
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
self as hir, AnonConst, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnRetTy, FnSig, GenericArg,
|
self as hir, AnonConst, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnRetTy, FnSig, GenericArg,
|
||||||
ImplItemKind, ItemKind, Lifetime, LifetimeName, Mutability, Node, Param, ParamName, PatKind, QPath, TraitFn,
|
ImplItemKind, ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, TraitFn, TraitItem, TraitItemKind,
|
||||||
TraitItem, TraitItemKind, TyKind, Unsafety,
|
TyKind, Unsafety,
|
||||||
};
|
};
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_infer::traits::{Obligation, ObligationCause};
|
use rustc_infer::traits::{Obligation, ObligationCause};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::ty::{self, Binder, ExistentialPredicate, List, PredicateKind, Ty};
|
use rustc_middle::ty::{self, Binder, Clause, ExistentialPredicate, List, PredicateKind, Ty};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::source_map::Span;
|
use rustc_span::source_map::Span;
|
||||||
use rustc_span::sym;
|
use rustc_span::sym;
|
||||||
|
@ -343,21 +343,16 @@ impl PtrArg<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RefPrefix {
|
struct RefPrefix {
|
||||||
lt: LifetimeName,
|
lt: Lifetime,
|
||||||
mutability: Mutability,
|
mutability: Mutability,
|
||||||
}
|
}
|
||||||
impl fmt::Display for RefPrefix {
|
impl fmt::Display for RefPrefix {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
use fmt::Write;
|
use fmt::Write;
|
||||||
f.write_char('&')?;
|
f.write_char('&')?;
|
||||||
match self.lt {
|
if !self.lt.is_anonymous() {
|
||||||
LifetimeName::Param(_, ParamName::Plain(name)) => {
|
self.lt.ident.fmt(f)?;
|
||||||
name.fmt(f)?;
|
f.write_char(' ')?;
|
||||||
f.write_char(' ')?;
|
|
||||||
},
|
|
||||||
LifetimeName::Infer => f.write_str("'_ ")?,
|
|
||||||
LifetimeName::Static => f.write_str("'static ")?,
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
f.write_str(self.mutability.prefix_str())
|
f.write_str(self.mutability.prefix_str())
|
||||||
}
|
}
|
||||||
|
@ -495,7 +490,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
|
||||||
ty_name: name.ident.name,
|
ty_name: name.ident.name,
|
||||||
method_renames,
|
method_renames,
|
||||||
ref_prefix: RefPrefix {
|
ref_prefix: RefPrefix {
|
||||||
lt: lt.name,
|
lt: *lt,
|
||||||
mutability,
|
mutability,
|
||||||
},
|
},
|
||||||
deref_ty,
|
deref_ty,
|
||||||
|
@ -687,24 +682,24 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
|
||||||
fn matches_preds<'tcx>(
|
fn matches_preds<'tcx>(
|
||||||
cx: &LateContext<'tcx>,
|
cx: &LateContext<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
preds: &'tcx [Binder<'tcx, ExistentialPredicate<'tcx>>],
|
preds: &'tcx [ty::PolyExistentialPredicate<'tcx>],
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let infcx = cx.tcx.infer_ctxt().build();
|
let infcx = cx.tcx.infer_ctxt().build();
|
||||||
preds.iter().all(|&p| match cx.tcx.erase_late_bound_regions(p) {
|
preds.iter().all(|&p| match cx.tcx.erase_late_bound_regions(p) {
|
||||||
ExistentialPredicate::Trait(p) => infcx
|
ExistentialPredicate::Trait(p) => infcx
|
||||||
.type_implements_trait(p.def_id, ty, p.substs, cx.param_env)
|
.type_implements_trait(p.def_id, [ty.into()].into_iter().chain(p.substs.iter()), cx.param_env)
|
||||||
.must_apply_modulo_regions(),
|
.must_apply_modulo_regions(),
|
||||||
ExistentialPredicate::Projection(p) => infcx.predicate_must_hold_modulo_regions(&Obligation::new(
|
ExistentialPredicate::Projection(p) => infcx.predicate_must_hold_modulo_regions(&Obligation::new(
|
||||||
cx.tcx,
|
cx.tcx,
|
||||||
ObligationCause::dummy(),
|
ObligationCause::dummy(),
|
||||||
cx.param_env,
|
cx.param_env,
|
||||||
cx.tcx.mk_predicate(Binder::bind_with_vars(
|
cx.tcx
|
||||||
PredicateKind::Projection(p.with_self_ty(cx.tcx, ty)),
|
.mk_predicate(Binder::dummy(PredicateKind::Clause(Clause::Projection(
|
||||||
List::empty(),
|
p.with_self_ty(cx.tcx, ty),
|
||||||
)),
|
)))),
|
||||||
)),
|
)),
|
||||||
ExistentialPredicate::AutoTrait(p) => infcx
|
ExistentialPredicate::AutoTrait(p) => infcx
|
||||||
.type_implements_trait(p, ty, List::empty(), cx.param_env)
|
.type_implements_trait(p, [ty], cx.param_env)
|
||||||
.must_apply_modulo_regions(),
|
.must_apply_modulo_regions(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -582,7 +582,7 @@ fn ident_difference_expr_with_base_location(
|
||||||
| (Block(_, _), Block(_, _))
|
| (Block(_, _), Block(_, _))
|
||||||
| (Closure(_), Closure(_))
|
| (Closure(_), Closure(_))
|
||||||
| (Match(_, _), Match(_, _))
|
| (Match(_, _), Match(_, _))
|
||||||
| (Loop(_, _), Loop(_, _))
|
| (Loop(_, _, _), Loop(_, _, _))
|
||||||
| (ForLoop(_, _, _, _), ForLoop(_, _, _, _))
|
| (ForLoop(_, _, _, _), ForLoop(_, _, _, _))
|
||||||
| (While(_, _, _), While(_, _, _))
|
| (While(_, _, _), While(_, _, _))
|
||||||
| (If(_, _, _), If(_, _, _))
|
| (If(_, _, _), If(_, _, _))
|
||||||
|
|
|
@ -31,10 +31,10 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ltopt = if lt.name.is_anonymous() {
|
let ltopt = if lt.is_anonymous() {
|
||||||
String::new()
|
String::new()
|
||||||
} else {
|
} else {
|
||||||
format!("{} ", lt.name.ident().as_str())
|
format!("{} ", lt.ident.as_str())
|
||||||
};
|
};
|
||||||
|
|
||||||
if mut_ty.mutbl == Mutability::Mut {
|
if mut_ty.mutbl == Mutability::Mut {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::{Closure, Expr, ExprKind, StmtKind};
|
use rustc_hir::{Closure, Expr, ExprKind, StmtKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_middle::ty::{GenericPredicates, PredicateKind, ProjectionPredicate, TraitPredicate};
|
use rustc_middle::ty::{Clause, GenericPredicates, PredicateKind, ProjectionPredicate, TraitPredicate};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::{sym, BytePos, Span};
|
use rustc_span::{sym, BytePos, Span};
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ fn get_trait_predicates_for_trait_id<'tcx>(
|
||||||
let mut preds = Vec::new();
|
let mut preds = Vec::new();
|
||||||
for (pred, _) in generics.predicates {
|
for (pred, _) in generics.predicates {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let PredicateKind::Trait(poly_trait_pred) = pred.kind().skip_binder();
|
if let PredicateKind::Clause(Clause::Trait(poly_trait_pred)) = pred.kind().skip_binder();
|
||||||
let trait_pred = cx.tcx.erase_late_bound_regions(pred.kind().rebind(poly_trait_pred));
|
let trait_pred = cx.tcx.erase_late_bound_regions(pred.kind().rebind(poly_trait_pred));
|
||||||
if let Some(trait_def_id) = trait_id;
|
if let Some(trait_def_id) = trait_id;
|
||||||
if trait_def_id == trait_pred.trait_ref.def_id;
|
if trait_def_id == trait_pred.trait_ref.def_id;
|
||||||
|
@ -63,7 +63,7 @@ fn get_projection_pred<'tcx>(
|
||||||
trait_pred: TraitPredicate<'tcx>,
|
trait_pred: TraitPredicate<'tcx>,
|
||||||
) -> Option<ProjectionPredicate<'tcx>> {
|
) -> Option<ProjectionPredicate<'tcx>> {
|
||||||
generics.predicates.iter().find_map(|(proj_pred, _)| {
|
generics.predicates.iter().find_map(|(proj_pred, _)| {
|
||||||
if let ty::PredicateKind::Projection(pred) = proj_pred.kind().skip_binder() {
|
if let ty::PredicateKind::Clause(Clause::Projection(pred)) = proj_pred.kind().skip_binder() {
|
||||||
let projection_pred = cx.tcx.erase_late_bound_regions(proj_pred.kind().rebind(pred));
|
let projection_pred = cx.tcx.erase_late_bound_regions(proj_pred.kind().rebind(pred));
|
||||||
if projection_pred.projection_ty.substs == trait_pred.trait_ref.substs {
|
if projection_pred.projection_ty.substs == trait_pred.trait_ref.substs {
|
||||||
return Some(projection_pred);
|
return Some(projection_pred);
|
||||||
|
|
|
@ -133,11 +133,11 @@ impl UnnecessaryDefPath {
|
||||||
let has_ctor = match cx.tcx.def_kind(def_id) {
|
let has_ctor = match cx.tcx.def_kind(def_id) {
|
||||||
DefKind::Struct => {
|
DefKind::Struct => {
|
||||||
let variant = cx.tcx.adt_def(def_id).non_enum_variant();
|
let variant = cx.tcx.adt_def(def_id).non_enum_variant();
|
||||||
variant.ctor_def_id.is_some() && variant.fields.iter().all(|f| f.vis.is_public())
|
variant.ctor.is_some() && variant.fields.iter().all(|f| f.vis.is_public())
|
||||||
},
|
},
|
||||||
DefKind::Variant => {
|
DefKind::Variant => {
|
||||||
let variant = cx.tcx.adt_def(cx.tcx.parent(def_id)).variant_with_id(def_id);
|
let variant = cx.tcx.adt_def(cx.tcx.parent(def_id)).variant_with_id(def_id);
|
||||||
variant.ctor_def_id.is_some() && variant.fields.iter().all(|f| f.vis.is_public())
|
variant.ctor.is_some() && variant.fields.iter().all(|f| f.vis.is_public())
|
||||||
},
|
},
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
|
@ -171,7 +171,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
|
||||||
(ForLoop(lp, li, lt, ll), ForLoop(rp, ri, rt, rl)) => {
|
(ForLoop(lp, li, lt, ll), ForLoop(rp, ri, rt, rl)) => {
|
||||||
eq_label(ll, rl) && eq_pat(lp, rp) && eq_expr(li, ri) && eq_block(lt, rt)
|
eq_label(ll, rl) && eq_pat(lp, rp) && eq_expr(li, ri) && eq_block(lt, rt)
|
||||||
},
|
},
|
||||||
(Loop(lt, ll), Loop(rt, rl)) => eq_label(ll, rl) && eq_block(lt, rt),
|
(Loop(lt, ll, _), Loop(rt, rl, _)) => eq_label(ll, rl) && eq_block(lt, rt),
|
||||||
(Block(lb, ll), Block(rb, rl)) => eq_label(ll, rl) && eq_block(lb, rb),
|
(Block(lb, ll), Block(rb, rl)) => eq_label(ll, rl) && eq_block(lb, rb),
|
||||||
(TryBlock(l), TryBlock(r)) => eq_block(l, r),
|
(TryBlock(l), TryBlock(r)) => eq_block(l, r),
|
||||||
(Yield(l), Yield(r)) | (Ret(l), Ret(r)) => eq_expr_opt(l, r),
|
(Yield(l), Yield(r)) | (Ret(l), Ret(r)) => eq_expr_opt(l, r),
|
||||||
|
@ -396,7 +396,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
||||||
&& over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind))
|
&& over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind))
|
||||||
},
|
},
|
||||||
(MacCall(l), MacCall(r)) => eq_mac_call(l, r),
|
(MacCall(l), MacCall(r)) => eq_mac_call(l, r),
|
||||||
(MacroDef(l), MacroDef(r)) => l.macro_rules == r.macro_rules && eq_mac_args(&l.body, &r.body),
|
(MacroDef(l), MacroDef(r)) => l.macro_rules == r.macro_rules && eq_delim_args(&l.body, &r.body),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -717,7 +717,7 @@ pub fn eq_assoc_constraint(l: &AssocConstraint, r: &AssocConstraint) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eq_mac_call(l: &MacCall, r: &MacCall) -> bool {
|
pub fn eq_mac_call(l: &MacCall, r: &MacCall) -> bool {
|
||||||
eq_path(&l.path, &r.path) && eq_mac_args(&l.args, &r.args)
|
eq_path(&l.path, &r.path) && eq_delim_args(&l.args, &r.args)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eq_attr(l: &Attribute, r: &Attribute) -> bool {
|
pub fn eq_attr(l: &Attribute, r: &Attribute) -> bool {
|
||||||
|
@ -725,18 +725,22 @@ pub fn eq_attr(l: &Attribute, r: &Attribute) -> bool {
|
||||||
l.style == r.style
|
l.style == r.style
|
||||||
&& match (&l.kind, &r.kind) {
|
&& match (&l.kind, &r.kind) {
|
||||||
(DocComment(l1, l2), DocComment(r1, r2)) => l1 == r1 && l2 == r2,
|
(DocComment(l1, l2), DocComment(r1, r2)) => l1 == r1 && l2 == r2,
|
||||||
(Normal(l), Normal(r)) => eq_path(&l.item.path, &r.item.path) && eq_mac_args(&l.item.args, &r.item.args),
|
(Normal(l), Normal(r)) => eq_path(&l.item.path, &r.item.path) && eq_attr_args(&l.item.args, &r.item.args),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eq_mac_args(l: &MacArgs, r: &MacArgs) -> bool {
|
pub fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool {
|
||||||
use MacArgs::*;
|
use AttrArgs::*;
|
||||||
match (l, r) {
|
match (l, r) {
|
||||||
(Empty, Empty) => true,
|
(Empty, Empty) => true,
|
||||||
(Delimited(_, ld, lts), Delimited(_, rd, rts)) => ld == rd && lts.eq_unspanned(rts),
|
(Delimited(la), Delimited(ra)) => eq_delim_args(la, ra),
|
||||||
(Eq(_, MacArgsEq::Ast(le)), Eq(_, MacArgsEq::Ast(re))) => eq_expr(le, re),
|
(Eq(_, AttrArgsEq::Ast(le)), Eq(_, AttrArgsEq::Ast(re))) => eq_expr(le, re),
|
||||||
(Eq(_, MacArgsEq::Hir(ll)), Eq(_, MacArgsEq::Hir(rl))) => ll.kind == rl.kind,
|
(Eq(_, AttrArgsEq::Hir(ll)), Eq(_, AttrArgsEq::Hir(rl))) => ll.kind == rl.kind,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn eq_delim_args(l: &DelimArgs, r: &DelimArgs) -> bool {
|
||||||
|
l.delim == r.delim && l.tokens.eq_unspanned(&r.tokens)
|
||||||
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ fn fn_eagerness(cx: &LateContext<'_>, fn_id: DefId, name: Symbol, have_one_arg:
|
||||||
.flat_map(|v| v.fields.iter())
|
.flat_map(|v| v.fields.iter())
|
||||||
.any(|x| matches!(cx.tcx.type_of(x.did).peel_refs().kind(), ty::Param(_)))
|
.any(|x| matches!(cx.tcx.type_of(x.did).peel_refs().kind(), ty::Param(_)))
|
||||||
&& all_predicates_of(cx.tcx, fn_id).all(|(pred, _)| match pred.kind().skip_binder() {
|
&& all_predicates_of(cx.tcx, fn_id).all(|(pred, _)| match pred.kind().skip_binder() {
|
||||||
PredicateKind::Trait(pred) => cx.tcx.trait_def(pred.trait_ref.def_id).is_marker,
|
PredicateKind::Clause(ty::Clause::Trait(pred)) => cx.tcx.trait_def(pred.trait_ref.def_id).is_marker,
|
||||||
_ => true,
|
_ => true,
|
||||||
})
|
})
|
||||||
&& subs.types().all(|x| matches!(x.peel_refs().kind(), ty::Param(_)))
|
&& subs.types().all(|x| matches!(x.peel_refs().kind(), ty::Param(_)))
|
||||||
|
|
|
@ -7,7 +7,7 @@ use rustc_hir::def::Res;
|
||||||
use rustc_hir::HirIdMap;
|
use rustc_hir::HirIdMap;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
ArrayLen, BinOpKind, BindingAnnotation, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg,
|
ArrayLen, BinOpKind, BindingAnnotation, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg,
|
||||||
GenericArgs, Guard, HirId, InlineAsmOperand, Let, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path,
|
GenericArgs, Guard, HirId, InlineAsmOperand, Let, Lifetime, LifetimeName, Pat, PatField, PatKind, Path,
|
||||||
PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding,
|
PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding,
|
||||||
};
|
};
|
||||||
use rustc_lexer::{tokenize, TokenKind};
|
use rustc_lexer::{tokenize, TokenKind};
|
||||||
|
@ -113,7 +113,7 @@ impl HirEqInterExpr<'_, '_, '_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// eq_pat adds the HirIds to the locals map. We therefor call it last to make sure that
|
// eq_pat adds the HirIds to the locals map. We therefore call it last to make sure that
|
||||||
// these only get added if the init and type is equal.
|
// these only get added if the init and type is equal.
|
||||||
both(&l.init, &r.init, |l, r| self.eq_expr(l, r))
|
both(&l.init, &r.init, |l, r| self.eq_expr(l, r))
|
||||||
&& both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r))
|
&& both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r))
|
||||||
|
@ -337,7 +337,7 @@ impl HirEqInterExpr<'_, '_, '_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eq_lifetime(left: &Lifetime, right: &Lifetime) -> bool {
|
fn eq_lifetime(left: &Lifetime, right: &Lifetime) -> bool {
|
||||||
left.name == right.name
|
left.res == right.res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eq_pat_field(&mut self, left: &PatField<'_>, right: &PatField<'_>) -> bool {
|
fn eq_pat_field(&mut self, left: &PatField<'_>, right: &PatField<'_>) -> bool {
|
||||||
|
@ -925,16 +925,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash_lifetime(&mut self, lifetime: &Lifetime) {
|
pub fn hash_lifetime(&mut self, lifetime: &Lifetime) {
|
||||||
std::mem::discriminant(&lifetime.name).hash(&mut self.s);
|
lifetime.ident.name.hash(&mut self.s);
|
||||||
if let LifetimeName::Param(param_id, ref name) = lifetime.name {
|
std::mem::discriminant(&lifetime.res).hash(&mut self.s);
|
||||||
std::mem::discriminant(name).hash(&mut self.s);
|
if let LifetimeName::Param(param_id) = lifetime.res {
|
||||||
param_id.hash(&mut self.s);
|
param_id.hash(&mut self.s);
|
||||||
match name {
|
|
||||||
ParamName::Plain(ref ident) => {
|
|
||||||
ident.name.hash(&mut self.s);
|
|
||||||
},
|
|
||||||
ParamName::Fresh | ParamName::Error => {},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,6 @@ pub const PEEKABLE: [&str; 5] = ["core", "iter", "adapters", "peekable", "Peekab
|
||||||
pub const PERMISSIONS: [&str; 3] = ["std", "fs", "Permissions"];
|
pub const PERMISSIONS: [&str; 3] = ["std", "fs", "Permissions"];
|
||||||
#[cfg_attr(not(unix), allow(clippy::invalid_paths))]
|
#[cfg_attr(not(unix), allow(clippy::invalid_paths))]
|
||||||
pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"];
|
pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"];
|
||||||
pub const POLL: [&str; 4] = ["core", "task", "poll", "Poll"];
|
|
||||||
pub const PTR_COPY: [&str; 3] = ["core", "intrinsics", "copy"];
|
pub const PTR_COPY: [&str; 3] = ["core", "intrinsics", "copy"];
|
||||||
pub const PTR_COPY_NONOVERLAPPING: [&str; 3] = ["core", "intrinsics", "copy_nonoverlapping"];
|
pub const PTR_COPY_NONOVERLAPPING: [&str; 3] = ["core", "intrinsics", "copy_nonoverlapping"];
|
||||||
pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"];
|
pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"];
|
||||||
|
|
|
@ -26,18 +26,21 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv)
|
||||||
let predicates = tcx.predicates_of(current);
|
let predicates = tcx.predicates_of(current);
|
||||||
for (predicate, _) in predicates.predicates {
|
for (predicate, _) in predicates.predicates {
|
||||||
match predicate.kind().skip_binder() {
|
match predicate.kind().skip_binder() {
|
||||||
ty::PredicateKind::RegionOutlives(_)
|
ty::PredicateKind::Clause(
|
||||||
| ty::PredicateKind::TypeOutlives(_)
|
ty::Clause::RegionOutlives(_)
|
||||||
|
| ty::Clause::TypeOutlives(_)
|
||||||
|
| ty::Clause::Projection(_)
|
||||||
|
| ty::Clause::Trait(..),
|
||||||
|
)
|
||||||
| ty::PredicateKind::WellFormed(_)
|
| ty::PredicateKind::WellFormed(_)
|
||||||
| ty::PredicateKind::Projection(_)
|
|
||||||
| ty::PredicateKind::ConstEvaluatable(..)
|
| ty::PredicateKind::ConstEvaluatable(..)
|
||||||
| ty::PredicateKind::ConstEquate(..)
|
| ty::PredicateKind::ConstEquate(..)
|
||||||
| ty::PredicateKind::Trait(..)
|
|
||||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
|
| ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
|
||||||
ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {predicate:#?}"),
|
ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {predicate:#?}"),
|
||||||
ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {predicate:#?}"),
|
ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {predicate:#?}"),
|
||||||
ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {predicate:#?}"),
|
ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {predicate:#?}"),
|
||||||
ty::PredicateKind::Coerce(_) => panic!("coerce predicate on function: {predicate:#?}"),
|
ty::PredicateKind::Coerce(_) => panic!("coerce predicate on function: {predicate:#?}"),
|
||||||
|
ty::PredicateKind::Ambiguous => panic!("ambiguous predicate on function: {predicate:#?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match predicates.parent {
|
match predicates.parent {
|
||||||
|
|
|
@ -9,20 +9,23 @@ use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
|
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety};
|
use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety};
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::{
|
||||||
|
type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
|
||||||
|
TyCtxtInferExt,
|
||||||
|
};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::mir::interpret::{ConstValue, Scalar};
|
use rustc_middle::mir::interpret::{ConstValue, Scalar};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, AdtDef, AssocKind, Binder, BoundRegion, DefIdTree, FnSig, GenericParamDefKind, IntTy, List, ParamEnv,
|
self, AdtDef, AssocKind, Binder, BoundRegion, DefIdTree, FnSig, IntTy, List, ParamEnv, Predicate, PredicateKind,
|
||||||
Predicate, PredicateKind, ProjectionTy, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable,
|
ProjectionTy, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
|
||||||
TypeVisitable, TypeVisitor, UintTy, VariantDef, VariantDiscr,
|
VariantDef, VariantDiscr,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{GenericArg, GenericArgKind};
|
use rustc_middle::ty::{GenericArg, GenericArgKind};
|
||||||
use rustc_span::symbol::Ident;
|
use rustc_span::symbol::Ident;
|
||||||
use rustc_span::{sym, Span, Symbol};
|
use rustc_span::{sym, Span, Symbol, DUMMY_SP};
|
||||||
use rustc_target::abi::{Size, VariantIdx};
|
use rustc_target::abi::{Size, VariantIdx};
|
||||||
use rustc_trait_selection::infer::InferCtxtExt;
|
use rustc_trait_selection::infer::InferCtxtExt;
|
||||||
use rustc_trait_selection::traits::query::normalize::AtExt;
|
use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use crate::{match_def_path, path_res, paths};
|
use crate::{match_def_path, path_res, paths};
|
||||||
|
@ -81,7 +84,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
|
||||||
match predicate.kind().skip_binder() {
|
match predicate.kind().skip_binder() {
|
||||||
// For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through
|
// For `impl Trait<U>`, it will register a predicate of `T: Trait<U>`, so we go through
|
||||||
// and check substituions to find `U`.
|
// and check substituions to find `U`.
|
||||||
ty::PredicateKind::Trait(trait_predicate) => {
|
ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) => {
|
||||||
if trait_predicate
|
if trait_predicate
|
||||||
.trait_ref
|
.trait_ref
|
||||||
.substs
|
.substs
|
||||||
|
@ -94,7 +97,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
|
||||||
},
|
},
|
||||||
// For `impl Trait<Assoc=U>`, it will register a predicate of `<T as Trait>::Assoc = U`,
|
// For `impl Trait<Assoc=U>`, it will register a predicate of `<T as Trait>::Assoc = U`,
|
||||||
// so we check the term for `U`.
|
// so we check the term for `U`.
|
||||||
ty::PredicateKind::Projection(projection_predicate) => {
|
ty::PredicateKind::Clause(ty::Clause::Projection(projection_predicate)) => {
|
||||||
if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack() {
|
if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack() {
|
||||||
if contains_ty_adt_constructor_opaque(cx, ty, needle) {
|
if contains_ty_adt_constructor_opaque(cx, ty, needle) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -117,24 +120,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
|
||||||
|
@ -206,7 +192,13 @@ pub fn implements_trait<'tcx>(
|
||||||
trait_id: DefId,
|
trait_id: DefId,
|
||||||
ty_params: &[GenericArg<'tcx>],
|
ty_params: &[GenericArg<'tcx>],
|
||||||
) -> bool {
|
) -> bool {
|
||||||
implements_trait_with_env(cx.tcx, cx.param_env, ty, trait_id, ty_params)
|
implements_trait_with_env(
|
||||||
|
cx.tcx,
|
||||||
|
cx.param_env,
|
||||||
|
ty,
|
||||||
|
trait_id,
|
||||||
|
ty_params.iter().map(|&arg| Some(arg)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context.
|
/// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context.
|
||||||
|
@ -215,7 +207,7 @@ pub fn implements_trait_with_env<'tcx>(
|
||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
trait_id: DefId,
|
trait_id: DefId,
|
||||||
ty_params: &[GenericArg<'tcx>],
|
ty_params: impl IntoIterator<Item = Option<GenericArg<'tcx>>>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
// Clippy shouldn't have infer types
|
// Clippy shouldn't have infer types
|
||||||
assert!(!ty.needs_infer());
|
assert!(!ty.needs_infer());
|
||||||
|
@ -224,10 +216,18 @@ pub fn implements_trait_with_env<'tcx>(
|
||||||
if ty.has_escaping_bound_vars() {
|
if ty.has_escaping_bound_vars() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let ty_params = tcx.mk_substs(ty_params.iter());
|
|
||||||
let infcx = tcx.infer_ctxt().build();
|
let infcx = tcx.infer_ctxt().build();
|
||||||
|
let orig = TypeVariableOrigin {
|
||||||
|
kind: TypeVariableOriginKind::MiscVariable,
|
||||||
|
span: DUMMY_SP,
|
||||||
|
};
|
||||||
|
let ty_params = tcx.mk_substs(
|
||||||
|
ty_params
|
||||||
|
.into_iter()
|
||||||
|
.map(|arg| arg.unwrap_or_else(|| infcx.next_ty_var(orig).into())),
|
||||||
|
);
|
||||||
infcx
|
infcx
|
||||||
.type_implements_trait(trait_id, ty, ty_params, param_env)
|
.type_implements_trait(trait_id, [ty.into()].into_iter().chain(ty_params), param_env)
|
||||||
.must_apply_modulo_regions()
|
.must_apply_modulo_regions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,7 +252,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||||
ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)),
|
ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)),
|
||||||
ty::Opaque(def_id, _) => {
|
ty::Opaque(def_id, _) => {
|
||||||
for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
|
for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
|
||||||
if let ty::PredicateKind::Trait(trait_predicate) = predicate.kind().skip_binder() {
|
if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() {
|
||||||
if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) {
|
if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -296,7 +296,7 @@ fn is_normalizable_helper<'tcx>(
|
||||||
cache.insert(ty, false);
|
cache.insert(ty, false);
|
||||||
let infcx = cx.tcx.infer_ctxt().build();
|
let infcx = cx.tcx.infer_ctxt().build();
|
||||||
let cause = rustc_middle::traits::ObligationCause::dummy();
|
let cause = rustc_middle::traits::ObligationCause::dummy();
|
||||||
let result = if infcx.at(&cause, param_env).normalize(ty).is_ok() {
|
let result = if infcx.at(&cause, param_env).query_normalize(ty).is_ok() {
|
||||||
match ty.kind() {
|
match ty.kind() {
|
||||||
ty::Adt(def, substs) => def.variants().iter().all(|variant| {
|
ty::Adt(def, substs) => def.variants().iter().all(|variant| {
|
||||||
variant
|
variant
|
||||||
|
@ -671,7 +671,7 @@ fn sig_from_bounds<'tcx>(
|
||||||
|
|
||||||
for pred in predicates {
|
for pred in predicates {
|
||||||
match pred.kind().skip_binder() {
|
match pred.kind().skip_binder() {
|
||||||
PredicateKind::Trait(p)
|
PredicateKind::Clause(ty::Clause::Trait(p))
|
||||||
if (lang_items.fn_trait() == Some(p.def_id())
|
if (lang_items.fn_trait() == Some(p.def_id())
|
||||||
|| lang_items.fn_mut_trait() == Some(p.def_id())
|
|| lang_items.fn_mut_trait() == Some(p.def_id())
|
||||||
|| lang_items.fn_once_trait() == Some(p.def_id()))
|
|| lang_items.fn_once_trait() == Some(p.def_id()))
|
||||||
|
@ -684,7 +684,7 @@ fn sig_from_bounds<'tcx>(
|
||||||
}
|
}
|
||||||
inputs = Some(i);
|
inputs = Some(i);
|
||||||
},
|
},
|
||||||
PredicateKind::Projection(p)
|
PredicateKind::Clause(ty::Clause::Projection(p))
|
||||||
if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output()
|
if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output()
|
||||||
&& p.projection_ty.self_ty() == ty =>
|
&& p.projection_ty.self_ty() == ty =>
|
||||||
{
|
{
|
||||||
|
@ -712,7 +712,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> O
|
||||||
.subst_iter_copied(cx.tcx, ty.substs)
|
.subst_iter_copied(cx.tcx, ty.substs)
|
||||||
{
|
{
|
||||||
match pred.kind().skip_binder() {
|
match pred.kind().skip_binder() {
|
||||||
PredicateKind::Trait(p)
|
PredicateKind::Clause(ty::Clause::Trait(p))
|
||||||
if (lang_items.fn_trait() == Some(p.def_id())
|
if (lang_items.fn_trait() == Some(p.def_id())
|
||||||
|| lang_items.fn_mut_trait() == Some(p.def_id())
|
|| lang_items.fn_mut_trait() == Some(p.def_id())
|
||||||
|| lang_items.fn_once_trait() == Some(p.def_id())) =>
|
|| lang_items.fn_once_trait() == Some(p.def_id())) =>
|
||||||
|
@ -725,7 +725,9 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> O
|
||||||
}
|
}
|
||||||
inputs = Some(i);
|
inputs = Some(i);
|
||||||
},
|
},
|
||||||
PredicateKind::Projection(p) if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output() => {
|
PredicateKind::Clause(ty::Clause::Projection(p))
|
||||||
|
if Some(p.projection_ty.item_def_id) == lang_items.fn_once_output() =>
|
||||||
|
{
|
||||||
if output.is_some() {
|
if output.is_some() {
|
||||||
// Multiple different fn trait impls. Is this even allowed?
|
// Multiple different fn trait impls. Is this even allowed?
|
||||||
return None;
|
return None;
|
||||||
|
@ -900,7 +902,7 @@ pub fn ty_is_fn_once_param<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, predicates: &'tc
|
||||||
predicates
|
predicates
|
||||||
.iter()
|
.iter()
|
||||||
.try_fold(false, |found, p| {
|
.try_fold(false, |found, p| {
|
||||||
if let PredicateKind::Trait(p) = p.kind().skip_binder()
|
if let PredicateKind::Clause(ty::Clause::Trait(p)) = p.kind().skip_binder()
|
||||||
&& let ty::Param(self_ty) = p.trait_ref.self_ty().kind()
|
&& let ty::Param(self_ty) = p.trait_ref.self_ty().kind()
|
||||||
&& ty.index == self_ty.index
|
&& ty.index == self_ty.index
|
||||||
{
|
{
|
||||||
|
@ -1010,7 +1012,7 @@ pub fn make_projection<'tcx>(
|
||||||
the given arguments are: `{substs:#?}`",
|
the given arguments are: `{substs:#?}`",
|
||||||
assoc_item.def_id,
|
assoc_item.def_id,
|
||||||
substs.len(),
|
substs.len(),
|
||||||
params.map(GenericParamDefKind::descr).collect::<Vec<_>>(),
|
params.map(ty::GenericParamDefKind::descr).collect::<Vec<_>>(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some((idx, (param, arg))) = params
|
if let Some((idx, (param, arg))) = params
|
||||||
|
@ -1020,9 +1022,9 @@ pub fn make_projection<'tcx>(
|
||||||
.find(|(_, (param, arg))| {
|
.find(|(_, (param, arg))| {
|
||||||
!matches!(
|
!matches!(
|
||||||
(param, arg),
|
(param, arg),
|
||||||
(GenericParamDefKind::Lifetime, GenericArgKind::Lifetime(_))
|
(ty::GenericParamDefKind::Lifetime, GenericArgKind::Lifetime(_))
|
||||||
| (GenericParamDefKind::Type { .. }, GenericArgKind::Type(_))
|
| (ty::GenericParamDefKind::Type { .. }, GenericArgKind::Type(_))
|
||||||
| (GenericParamDefKind::Const { .. }, GenericArgKind::Const(_))
|
| (ty::GenericParamDefKind::Const { .. }, GenericArgKind::Const(_))
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
@ -1032,7 +1034,7 @@ pub fn make_projection<'tcx>(
|
||||||
note: the expected parameters are {:#?}\n\
|
note: the expected parameters are {:#?}\n\
|
||||||
the given arguments are {substs:#?}",
|
the given arguments are {substs:#?}",
|
||||||
param.descr(),
|
param.descr(),
|
||||||
params.map(GenericParamDefKind::descr).collect::<Vec<_>>()
|
params.map(ty::GenericParamDefKind::descr).collect::<Vec<_>>()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,3 +11,6 @@ proc-macro = true
|
||||||
itertools = "0.10.1"
|
itertools = "0.10.1"
|
||||||
quote = "1.0.21"
|
quote = "1.0.21"
|
||||||
syn = "1.0.100"
|
syn = "1.0.100"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
deny-warnings = []
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
||||||
|
// warn on lints, that are included in `rust-lang/rust`s bootstrap
|
||||||
|
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
@ -29,7 +31,7 @@ struct ClippyLint {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for ClippyLint {
|
impl Parse for ClippyLint {
|
||||||
fn parse(input: ParseStream) -> Result<Self> {
|
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
||||||
let attrs = input.call(Attribute::parse_outer)?;
|
let attrs = input.call(Attribute::parse_outer)?;
|
||||||
|
|
||||||
let mut in_code = false;
|
let mut in_code = false;
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly-2022-11-21"
|
channel = "nightly-2022-12-01"
|
||||||
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(once_cell)]
|
#![feature(once_cell)]
|
||||||
|
#![feature(lint_reasons)]
|
||||||
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
||||||
// warn on lints, that are included in `rust-lang/rust`s bootstrap
|
// warn on lints, that are included in `rust-lang/rust`s bootstrap
|
||||||
#![warn(rust_2018_idioms, unused_lifetimes)]
|
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||||
|
@ -90,11 +91,16 @@ fn track_files(parse_sess: &mut ParseSess, conf_path_string: Option<String>) {
|
||||||
|
|
||||||
// During development track the `clippy-driver` executable so that cargo will re-run clippy whenever
|
// During development track the `clippy-driver` executable so that cargo will re-run clippy whenever
|
||||||
// it is rebuilt
|
// it is rebuilt
|
||||||
if cfg!(debug_assertions)
|
#[expect(
|
||||||
&& let Ok(current_exe) = env::current_exe()
|
clippy::collapsible_if,
|
||||||
&& let Some(current_exe) = current_exe.to_str()
|
reason = "Due to a bug in let_chains this if statement can't be collapsed"
|
||||||
{
|
)]
|
||||||
file_depinfo.insert(Symbol::intern(current_exe));
|
if cfg!(debug_assertions) {
|
||||||
|
if let Ok(current_exe) = env::current_exe()
|
||||||
|
&& let Some(current_exe) = current_exe.to_str()
|
||||||
|
{
|
||||||
|
file_depinfo.insert(Symbol::intern(current_exe));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,3 @@
|
||||||
error: hardcoded path to a language item
|
|
||||||
--> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
|
|
||||||
|
|
|
||||||
LL | const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"];
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= help: convert all references to use `LangItem::DerefMut`
|
|
||||||
= note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
|
|
||||||
|
|
||||||
error: hardcoded path to a diagnostic item
|
error: hardcoded path to a diagnostic item
|
||||||
--> $DIR/unnecessary_def_path_hardcoded_path.rs:10:36
|
--> $DIR/unnecessary_def_path_hardcoded_path.rs:10:36
|
||||||
|
|
|
|
||||||
|
@ -14,6 +5,7 @@ LL | const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: convert all references to use `sym::Deref`
|
= help: convert all references to use `sym::Deref`
|
||||||
|
= note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
|
||||||
|
|
||||||
error: hardcoded path to a diagnostic item
|
error: hardcoded path to a diagnostic item
|
||||||
--> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
|
--> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
|
||||||
|
@ -23,5 +15,13 @@ LL | const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref",
|
||||||
|
|
|
|
||||||
= help: convert all references to use `sym::deref_method`
|
= help: convert all references to use `sym::deref_method`
|
||||||
|
|
||||||
|
error: hardcoded path to a language item
|
||||||
|
--> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
|
||||||
|
|
|
||||||
|
LL | const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"];
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: convert all references to use `LangItem::DerefMut`
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,14 @@ error: an async construct yields a type which is itself awaitable
|
||||||
--> $DIR/async_yields_async.rs:39:9
|
--> $DIR/async_yields_async.rs:39:9
|
||||||
|
|
|
|
||||||
LL | let _h = async {
|
LL | let _h = async {
|
||||||
| ____________________-
|
| _____________________-
|
||||||
LL | | async {
|
LL | | async {
|
||||||
| |_________^
|
| | _________^
|
||||||
LL | || 3
|
LL | || 3
|
||||||
LL | || }
|
LL | || }
|
||||||
| ||_________^ awaitable value not awaited
|
| ||_________^ awaitable value not awaited
|
||||||
LL | | };
|
LL | | };
|
||||||
| |_____- outer async construct
|
| |______- outer async construct
|
||||||
|
|
|
|
||||||
= note: `-D clippy::async-yields-async` implied by `-D warnings`
|
= note: `-D clippy::async-yields-async` implied by `-D warnings`
|
||||||
help: consider awaiting this value
|
help: consider awaiting this value
|
||||||
|
@ -36,14 +36,14 @@ error: an async construct yields a type which is itself awaitable
|
||||||
--> $DIR/async_yields_async.rs:50:9
|
--> $DIR/async_yields_async.rs:50:9
|
||||||
|
|
|
|
||||||
LL | let _j = async || {
|
LL | let _j = async || {
|
||||||
| _______________________-
|
| ________________________-
|
||||||
LL | | async {
|
LL | | async {
|
||||||
| |_________^
|
| | _________^
|
||||||
LL | || 3
|
LL | || 3
|
||||||
LL | || }
|
LL | || }
|
||||||
| ||_________^ awaitable value not awaited
|
| ||_________^ awaitable value not awaited
|
||||||
LL | | };
|
LL | | };
|
||||||
| |_____- outer async construct
|
| |______- outer async construct
|
||||||
|
|
|
|
||||||
help: consider awaiting this value
|
help: consider awaiting this value
|
||||||
|
|
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ if let ExprKind::Closure(CaptureBy::Value, fn_decl, body_id, _, None) = expr.kin
|
||||||
&& expr1 = &cx.tcx.hir().body(body_id).value
|
&& expr1 = &cx.tcx.hir().body(body_id).value
|
||||||
&& let ExprKind::Call(func, args) = expr1.kind
|
&& let ExprKind::Call(func, args) = expr1.kind
|
||||||
&& let ExprKind::Path(ref qpath) = func.kind
|
&& let ExprKind::Path(ref qpath) = func.kind
|
||||||
&& matches!(qpath, QPath::LangItem(LangItem::FromGenerator, _))
|
&& matches!(qpath, QPath::LangItem(LangItem::IdentityFuture, _))
|
||||||
&& args.len() == 1
|
&& args.len() == 1
|
||||||
&& let ExprKind::Closure(CaptureBy::Value, fn_decl1, body_id1, _, Some(Movability::Static)) = args[0].kind
|
&& let ExprKind::Closure(CaptureBy::Value, fn_decl1, body_id1, _, Some(Movability::Static)) = args[0].kind
|
||||||
&& let FnRetTy::DefaultReturn(_) = fn_decl1.output
|
&& let FnRetTy::DefaultReturn(_) = fn_decl1.output
|
||||||
|
|
|
@ -20,14 +20,14 @@ error: called `map(f)` on an `Result` value where `f` is a closure that returns
|
||||||
--> $DIR/result_map_unit_fn_unfixable.rs:29:5
|
--> $DIR/result_map_unit_fn_unfixable.rs:29:5
|
||||||
|
|
|
|
||||||
LL | x.field.map(|value| {
|
LL | x.field.map(|value| {
|
||||||
| _____^
|
| ______^
|
||||||
| |_____|
|
| | _____|
|
||||||
| ||
|
| ||
|
||||||
LL | || do_nothing(value);
|
LL | || do_nothing(value);
|
||||||
LL | || do_nothing(value)
|
LL | || do_nothing(value)
|
||||||
LL | || });
|
LL | || });
|
||||||
| ||______^- help: try this: `if let Ok(value) = x.field { ... }`
|
| ||______^- help: try this: `if let Ok(value) = x.field { ... }`
|
||||||
| |_______|
|
| |______|
|
||||||
|
|
|
|
||||||
|
|
||||||
error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()`
|
error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()`
|
||||||
|
|
Loading…
Reference in a new issue