Auto merge of #10010 - flip1995:rustup, r=flip1995

Rustup

r? `@ghost`

changelog: none
This commit is contained in:
bors 2022-12-01 13:21:51 +00:00
commit d822110d3b
39 changed files with 230 additions and 219 deletions

View file

@ -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";

View file

@ -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;

View file

@ -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()

View file

@ -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 => "",

View file

@ -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(

View file

@ -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)

View file

@ -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,

View file

@ -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(

View file

@ -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.

View file

@ -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(),

View file

@ -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;

View file

@ -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;
} }
} }

View file

@ -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 {

View file

@ -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 => "{ .. }",
} }
) )
}; };

View file

@ -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();

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

@ -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,8 +407,10 @@ 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()
&& trait_predicate.trait_ref.self_ty() == *param_ty
{
true true
} else { } 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 {

View file

@ -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;

View file

@ -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;
} }

View file

@ -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(),
}) })
} }

View file

@ -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(_, _, _))

View file

@ -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 {

View file

@ -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);

View file

@ -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,
}; };

View file

@ -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)
}

View file

@ -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(_)))

View file

@ -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 => {},
}
} }
} }

View file

@ -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"];

View file

@ -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 {

View file

@ -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<_>>()
); );
} }
} }

View file

@ -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 = []

View file

@ -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;

View file

@ -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"]

View file

@ -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,12 +91,17 @@ 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,
reason = "Due to a bug in let_chains this if statement can't be collapsed"
)]
if cfg!(debug_assertions) {
if let Ok(current_exe) = env::current_exe()
&& let Some(current_exe) = current_exe.to_str() && let Some(current_exe) = current_exe.to_str()
{ {
file_depinfo.insert(Symbol::intern(current_exe)); file_depinfo.insert(Symbol::intern(current_exe));
} }
}
} }
struct DefaultCallbacks; struct DefaultCallbacks;

View file

@ -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

View file

@ -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
| |

View file

@ -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

View file

@ -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 `()`