commit
d1d0fee887
101 changed files with 380 additions and 453 deletions
|
@ -6,8 +6,8 @@ use clippy_config::types::{
|
|||
};
|
||||
use clippy_utils::diagnostics::span_lint_and_note;
|
||||
use rustc_hir::{
|
||||
AssocItemKind, FieldDef, HirId, ImplItemRef, IsAuto, Item, ItemKind, Mod, QPath, TraitItemRef, TyKind, UseKind,
|
||||
Variant, VariantData,
|
||||
AssocItemKind, FieldDef, HirId, ImplItemRef, IsAuto, Item, ItemKind, Mod, QPath, TraitItemRef, TyKind, Variant,
|
||||
VariantData,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_session::impl_lint_pass;
|
||||
|
@ -202,11 +202,7 @@ impl ArbitrarySourceItemOrdering {
|
|||
}
|
||||
|
||||
/// Produces a linting warning for incorrectly ordered item members.
|
||||
fn lint_member_name<T: LintContext>(
|
||||
cx: &T,
|
||||
ident: &rustc_span::symbol::Ident,
|
||||
before_ident: &rustc_span::symbol::Ident,
|
||||
) {
|
||||
fn lint_member_name<T: LintContext>(cx: &T, ident: &rustc_span::Ident, before_ident: &rustc_span::Ident) {
|
||||
span_lint_and_note(
|
||||
cx,
|
||||
ARBITRARY_SOURCE_ITEM_ORDERING,
|
||||
|
@ -218,21 +214,18 @@ impl ArbitrarySourceItemOrdering {
|
|||
}
|
||||
|
||||
fn lint_member_item<T: LintContext>(cx: &T, item: &Item<'_>, before_item: &Item<'_>, msg: &'static str) {
|
||||
let span = if item.ident.as_str().is_empty() {
|
||||
&item.span
|
||||
let span = if let Some(ident) = item.kind.ident() {
|
||||
ident.span
|
||||
} else {
|
||||
&item.ident.span
|
||||
item.span
|
||||
};
|
||||
|
||||
let (before_span, note) = if before_item.ident.as_str().is_empty() {
|
||||
(
|
||||
&before_item.span,
|
||||
"should be placed before the following item".to_owned(),
|
||||
)
|
||||
let (before_span, note) = if let Some(ident) = before_item.kind.ident() {
|
||||
(ident.span, format!("should be placed before `{}`", ident.as_str(),))
|
||||
} else {
|
||||
(
|
||||
&before_item.ident.span,
|
||||
format!("should be placed before `{}`", before_item.ident.as_str(),),
|
||||
before_item.span,
|
||||
"should be placed before the following item".to_owned(),
|
||||
)
|
||||
};
|
||||
|
||||
|
@ -241,7 +234,7 @@ impl ArbitrarySourceItemOrdering {
|
|||
return;
|
||||
}
|
||||
|
||||
span_lint_and_note(cx, ARBITRARY_SOURCE_ITEM_ORDERING, *span, msg, Some(*before_span), note);
|
||||
span_lint_and_note(cx, ARBITRARY_SOURCE_ITEM_ORDERING, span, msg, Some(before_span), note);
|
||||
}
|
||||
|
||||
/// Produces a linting warning for incorrectly ordered trait items.
|
||||
|
@ -263,7 +256,7 @@ impl ArbitrarySourceItemOrdering {
|
|||
impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
match &item.kind {
|
||||
ItemKind::Enum(enum_def, _generics) if self.enable_ordering_for_enum => {
|
||||
ItemKind::Enum(_, enum_def, _generics) if self.enable_ordering_for_enum => {
|
||||
let mut cur_v: Option<&Variant<'_>> = None;
|
||||
for variant in enum_def.variants {
|
||||
if variant.span.in_external_macro(cx.sess().source_map()) {
|
||||
|
@ -278,7 +271,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
|
|||
cur_v = Some(variant);
|
||||
}
|
||||
},
|
||||
ItemKind::Struct(VariantData::Struct { fields, .. }, _generics) if self.enable_ordering_for_struct => {
|
||||
ItemKind::Struct(_, VariantData::Struct { fields, .. }, _generics) if self.enable_ordering_for_struct => {
|
||||
let mut cur_f: Option<&FieldDef<'_>> = None;
|
||||
for field in *fields {
|
||||
if field.span.in_external_macro(cx.sess().source_map()) {
|
||||
|
@ -293,7 +286,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
|
|||
cur_f = Some(field);
|
||||
}
|
||||
},
|
||||
ItemKind::Trait(is_auto, _safety, _generics, _generic_bounds, item_ref)
|
||||
ItemKind::Trait(is_auto, _safety, _ident, _generics, _generic_bounds, item_ref)
|
||||
if self.enable_ordering_for_trait && *is_auto == IsAuto::No =>
|
||||
{
|
||||
let mut cur_t: Option<&TraitItemRef> = None;
|
||||
|
@ -370,50 +363,24 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
|
|||
continue;
|
||||
}
|
||||
|
||||
// The following exceptions (skipping with `continue;`) may not be
|
||||
// complete, edge cases have not been explored further than what
|
||||
// appears in the existing code base.
|
||||
if item.ident.name == rustc_span::symbol::kw::Empty {
|
||||
if let ItemKind::Impl(_) = item.kind {
|
||||
// Sorting trait impls for unnamed types makes no sense.
|
||||
if get_item_name(item).is_empty() {
|
||||
continue;
|
||||
}
|
||||
} else if let ItemKind::ForeignMod { .. } = item.kind {
|
||||
continue;
|
||||
} else if let ItemKind::GlobalAsm { .. } = item.kind {
|
||||
continue;
|
||||
} else if let ItemKind::Use(path, use_kind) = item.kind {
|
||||
if path.segments.is_empty() {
|
||||
// Use statements that contain braces get caught here.
|
||||
// They will still be linted internally.
|
||||
continue;
|
||||
} else if path.segments.len() >= 2
|
||||
&& (path.segments[0].ident.name == rustc_span::sym::std
|
||||
|| path.segments[0].ident.name == rustc_span::sym::core)
|
||||
&& path.segments[1].ident.name == rustc_span::sym::prelude
|
||||
{
|
||||
// Filters the autogenerated prelude use statement.
|
||||
// e.g. `use std::prelude::rustc_2021`
|
||||
} else if use_kind == UseKind::Glob {
|
||||
// Filters glob kinds of uses.
|
||||
// e.g. `use std::sync::*`
|
||||
} else {
|
||||
// This can be used for debugging.
|
||||
// println!("Unknown autogenerated use statement: {:?}", item);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let ident = if let Some(ident) = item.kind.ident() {
|
||||
ident
|
||||
} else if let ItemKind::Impl(_) = item.kind
|
||||
&& !get_item_name(item).is_empty()
|
||||
{
|
||||
rustc_span::Ident::empty() // FIXME: a bit strange, is there a better way to do it?
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if item.ident.name.as_str().starts_with('_') {
|
||||
if ident.name.as_str().starts_with('_') {
|
||||
// Filters out unnamed macro-like impls for various derives,
|
||||
// e.g. serde::Serialize or num_derive::FromPrimitive.
|
||||
continue;
|
||||
}
|
||||
|
||||
if item.ident.name == rustc_span::sym::std && item.span.is_dummy() {
|
||||
if let ItemKind::ExternCrate(None) = item.kind {
|
||||
if ident.name == rustc_span::sym::std && item.span.is_dummy() {
|
||||
if let ItemKind::ExternCrate(None, _) = item.kind {
|
||||
// Filters the auto-included Rust standard library.
|
||||
continue;
|
||||
}
|
||||
|
@ -559,6 +526,14 @@ fn get_item_name(item: &Item<'_>) -> String {
|
|||
String::new()
|
||||
}
|
||||
},
|
||||
_ => item.ident.name.as_str().to_owned(),
|
||||
// FIXME: `Ident::empty` for anonymous items is a bit strange, is there
|
||||
// a better way to do it?
|
||||
_ => item
|
||||
.kind
|
||||
.ident()
|
||||
.unwrap_or(rustc_span::Ident::empty())
|
||||
.name
|
||||
.as_str()
|
||||
.to_owned(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ mod utils;
|
|||
use clippy_config::Conf;
|
||||
use clippy_utils::msrvs::{self, Msrv, MsrvStack};
|
||||
use rustc_ast::{self as ast, Attribute, MetaItemInner, MetaItemKind};
|
||||
use rustc_hir::{ImplItem, Item, TraitItem};
|
||||
use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::sym;
|
||||
|
@ -465,22 +465,24 @@ impl Attributes {
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for Attributes {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||
if is_relevant_item(cx, item) {
|
||||
inline_always::check(cx, item.span, item.ident.name, attrs);
|
||||
let attrs = cx.tcx.hir_attrs(item.hir_id());
|
||||
if let ItemKind::Fn { ident, .. } = item.kind
|
||||
&& is_relevant_item(cx, item)
|
||||
{
|
||||
inline_always::check(cx, item.span, ident.name, attrs);
|
||||
}
|
||||
repr_attributes::check(cx, item.span, attrs, self.msrv);
|
||||
}
|
||||
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
|
||||
if is_relevant_impl(cx, item) {
|
||||
inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()));
|
||||
inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir_attrs(item.hir_id()));
|
||||
}
|
||||
}
|
||||
|
||||
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
|
||||
if is_relevant_trait(cx, item) {
|
||||
inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()));
|
||||
inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir_attrs(item.hir_id()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ pub(super) fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
|
|||
if let ItemKind::Fn { body: eid, .. } = item.kind {
|
||||
is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir_body(eid).value)
|
||||
} else {
|
||||
true
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ fn is_zst<'tcx>(cx: &LateContext<'tcx>, field: &FieldDef, args: ty::GenericArgsR
|
|||
}
|
||||
|
||||
fn has_c_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
|
||||
let attrs = cx.tcx.hir().attrs(hir_id);
|
||||
let attrs = cx.tcx.hir_attrs(hir_id);
|
||||
|
||||
find_attr!(attrs, AttributeKind::Repr(r) if r.iter().any(|(x, _)| *x == ReprAttr::ReprC))
|
||||
}
|
||||
|
|
|
@ -197,9 +197,9 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
|
|||
&& let ImplItemKind::Fn(_, b) = &impl_item.kind
|
||||
&& let Body { value: func_expr, .. } = cx.tcx.hir_body(*b)
|
||||
&& let &ty::Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind()
|
||||
&& let attrs = cx.tcx.hir().attrs(item.hir_id())
|
||||
&& let attrs = cx.tcx.hir_attrs(item.hir_id())
|
||||
&& !attrs.iter().any(|attr| attr.doc_str().is_some())
|
||||
&& cx.tcx.hir().attrs(impl_item_hir).is_empty()
|
||||
&& cx.tcx.hir_attrs(impl_item_hir).is_empty()
|
||||
{
|
||||
if adt_def.is_struct() {
|
||||
check_struct(cx, item, self_ty, func_expr, adt_def, args, cx.tcx.typeck_body(*b));
|
||||
|
|
|
@ -384,7 +384,7 @@ fn check_unsafe_derive_deserialize<'tcx>(
|
|||
.tcx
|
||||
.inherent_impls(def.did())
|
||||
.iter()
|
||||
.map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local()))
|
||||
.map(|imp_did| cx.tcx.hir_expect_item(imp_did.expect_local()))
|
||||
.any(|imp| has_unsafe(cx, imp))
|
||||
{
|
||||
span_lint_hir_and_then(
|
||||
|
|
|
@ -99,7 +99,7 @@ impl_lint_pass!(DisallowedTypes => [DISALLOWED_TYPES]);
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
if let ItemKind::Use(path, UseKind::Single) = &item.kind {
|
||||
if let ItemKind::Use(path, UseKind::Single(_)) = &item.kind {
|
||||
for res in &path.res {
|
||||
self.check_res_emit(cx, res, item.span);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ pub fn check(
|
|||
&& cx
|
||||
.tcx
|
||||
.hir_parent_iter(owner_id.into())
|
||||
.any(|(id, _node)| is_doc_hidden(cx.tcx.hir().attrs(id)))
|
||||
.any(|(id, _node)| is_doc_hidden(cx.tcx.hir_attrs(id)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
|
|||
if cx.tcx.data_layout.pointer_size.bits() != 64 {
|
||||
return;
|
||||
}
|
||||
if let ItemKind::Enum(def, _) = &item.kind {
|
||||
if let ItemKind::Enum(_, def, _) = &item.kind {
|
||||
for var in def.variants {
|
||||
if let Some(anon_const) = &var.disr_expr {
|
||||
let def_id = cx.tcx.hir_body_owner_def_id(anon_const.body);
|
||||
|
|
|
@ -37,8 +37,8 @@ declare_lint_pass!(ErrorImplError => [ERROR_IMPL_ERROR]);
|
|||
impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
match item.kind {
|
||||
ItemKind::TyAlias(..)
|
||||
if item.ident.name == sym::Error
|
||||
ItemKind::TyAlias(ident, ..)
|
||||
if ident.name == sym::Error
|
||||
&& is_visible_outside_module(cx, item.owner_id.def_id)
|
||||
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
|
||||
&& let Some(error_def_id) = cx.tcx.get_diagnostic_item(sym::Error)
|
||||
|
@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
|
|||
span_lint(
|
||||
cx,
|
||||
ERROR_IMPL_ERROR,
|
||||
item.ident.span,
|
||||
ident.span,
|
||||
"exported type alias named `Error` that implements `Error`",
|
||||
);
|
||||
},
|
||||
|
|
|
@ -91,7 +91,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
|
|||
}
|
||||
|
||||
// find `self` ty for this trait if relevant
|
||||
if let ItemKind::Trait(_, _, _, _, items) = item.kind {
|
||||
if let ItemKind::Trait(_, _, _, _, _, items) = item.kind {
|
||||
for trait_item in items {
|
||||
if trait_item.id.owner_id.def_id == fn_def_id {
|
||||
// be sure we have `self` parameter in this function
|
||||
|
@ -150,6 +150,8 @@ impl<'tcx> Delegate<'tcx> for EscapeDelegate<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||
|
||||
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {
|
||||
if cmt.place.projections.is_empty() {
|
||||
if let PlaceBase::Local(lid) = cmt.place.base {
|
||||
|
@ -160,26 +162,23 @@ impl<'tcx> Delegate<'tcx> for EscapeDelegate<'_, 'tcx> {
|
|||
}
|
||||
|
||||
fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId) {
|
||||
if cmt.place.projections.is_empty() {
|
||||
let map = &self.cx.tcx.hir();
|
||||
if is_argument(self.cx.tcx, cmt.hir_id) {
|
||||
// Skip closure arguments
|
||||
let parent_id = self.cx.tcx.parent_hir_id(cmt.hir_id);
|
||||
if let Node::Expr(..) = self.cx.tcx.parent_hir_node(parent_id) {
|
||||
if cmt.place.projections.is_empty() && is_argument(self.cx.tcx, cmt.hir_id) {
|
||||
// Skip closure arguments
|
||||
let parent_id = self.cx.tcx.parent_hir_id(cmt.hir_id);
|
||||
if let Node::Expr(..) = self.cx.tcx.parent_hir_node(parent_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
// skip if there is a `self` parameter binding to a type
|
||||
// that contains `Self` (i.e.: `self: Box<Self>`), see #4804
|
||||
if let Some(trait_self_ty) = self.trait_self_ty {
|
||||
if self.cx.tcx.hir_name(cmt.hir_id) == kw::SelfLower && cmt.place.ty().contains(trait_self_ty) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// skip if there is a `self` parameter binding to a type
|
||||
// that contains `Self` (i.e.: `self: Box<Self>`), see #4804
|
||||
if let Some(trait_self_ty) = self.trait_self_ty {
|
||||
if map.name(cmt.hir_id) == kw::SelfLower && cmt.place.ty().contains(trait_self_ty) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if is_non_trait_box(cmt.place.ty()) && !self.is_large_box(cmt.place.ty()) {
|
||||
self.set.insert(cmt.hir_id);
|
||||
}
|
||||
if is_non_trait_box(cmt.place.ty()) && !self.is_large_box(cmt.place.ty()) {
|
||||
self.set.insert(cmt.hir_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ fn check_fn_decl(cx: &LateContext<'_>, decl: &FnDecl<'_>, sp: Span, max: u64) {
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
if let ItemKind::Struct(variant_data, _) = &item.kind
|
||||
if let ItemKind::Struct(_, variant_data, _) = &item.kind
|
||||
&& variant_data.fields().len() as u64 > self.max_struct_bools
|
||||
&& has_n_bools(
|
||||
variant_data.fields().iter().map(|field| field.ty),
|
||||
|
|
|
@ -76,7 +76,7 @@ impl LateLintPass<'_> for ExhaustiveItems {
|
|||
"exported enums should not be exhaustive",
|
||||
[].as_slice(),
|
||||
),
|
||||
ItemKind::Struct(v, ..) => (
|
||||
ItemKind::Struct(_, v, ..) => (
|
||||
EXHAUSTIVE_STRUCTS,
|
||||
"exported structs should not be exhaustive",
|
||||
v.fields(),
|
||||
|
@ -84,7 +84,7 @@ impl LateLintPass<'_> for ExhaustiveItems {
|
|||
_ => return,
|
||||
};
|
||||
if cx.effective_visibilities.is_exported(item.owner_id.def_id)
|
||||
&& let attrs = cx.tcx.hir().attrs(item.hir_id())
|
||||
&& let attrs = cx.tcx.hir_attrs(item.hir_id())
|
||||
&& !attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
|
||||
&& fields.iter().all(|f| cx.tcx.visibility(f.def_id).is_public())
|
||||
{
|
||||
|
|
|
@ -209,9 +209,8 @@ impl FormatImplExpr<'_, '_> {
|
|||
// Handle dereference of &self -> self that is equivalent (i.e. via *self in fmt() impl)
|
||||
// Since the argument to fmt is itself a reference: &self
|
||||
let reference = peel_ref_operators(self.cx, arg);
|
||||
let map = self.cx.tcx.hir();
|
||||
// Is the reference self?
|
||||
if path_to_local(reference).map(|x| map.name(x)) == Some(kw::SelfLower) {
|
||||
if path_to_local(reference).map(|x| self.cx.tcx.hir_name(x)) == Some(kw::SelfLower) {
|
||||
let FormatTraitNames { name, .. } = self.format_trait_impl;
|
||||
span_lint(
|
||||
self.cx,
|
||||
|
|
|
@ -43,8 +43,7 @@ impl<'tcx> LateLintPass<'tcx> for FourForwardSlashes {
|
|||
let sm = cx.sess().source_map();
|
||||
let mut span = cx
|
||||
.tcx
|
||||
.hir()
|
||||
.attrs(item.hir_id())
|
||||
.hir_attrs(item.hir_id())
|
||||
.iter()
|
||||
.filter(|i| i.is_doc_comment())
|
||||
.fold(item.span.shrink_to_lo(), |span, attr| span.to(attr.span()));
|
||||
|
|
|
@ -21,7 +21,7 @@ use core::ops::ControlFlow;
|
|||
use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT};
|
||||
|
||||
pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
|
||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||
let attrs = cx.tcx.hir_attrs(item.hir_id());
|
||||
let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
|
||||
if let hir::ItemKind::Fn {
|
||||
ref sig,
|
||||
|
@ -51,7 +51,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
|
|||
if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind {
|
||||
let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
|
||||
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
|
||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||
let attrs = cx.tcx.hir_attrs(item.hir_id());
|
||||
let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
|
||||
if let Some(attr) = attr {
|
||||
check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig);
|
||||
|
@ -74,7 +74,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
|
|||
let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
|
||||
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
|
||||
|
||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||
let attrs = cx.tcx.hir_attrs(item.hir_id());
|
||||
let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
|
||||
if let Some(attr) = attr {
|
||||
check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig);
|
||||
|
|
|
@ -103,7 +103,7 @@ fn check_result_large_err<'tcx>(cx: &LateContext<'tcx>, err_ty: Ty<'tcx>, hir_ty
|
|||
.did()
|
||||
.as_local()
|
||||
&& let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(local_def_id)
|
||||
&& let hir::ItemKind::Enum(ref def, _) = item.kind
|
||||
&& let hir::ItemKind::Enum(_, ref def, _) = item.kind
|
||||
{
|
||||
let variants_size = AdtVariantInfo::new(cx, *adt, subst);
|
||||
if let Some((first_variant, variants)) = variants_size.split_first()
|
||||
|
|
|
@ -182,7 +182,7 @@ fn suggestion<'tcx>(
|
|||
}
|
||||
|
||||
fn field_with_attrs_span(tcx: TyCtxt<'_>, field: &hir::ExprField<'_>) -> Span {
|
||||
if let Some(attr) = tcx.hir().attrs(field.hir_id).first() {
|
||||
if let Some(attr) = tcx.hir_attrs(field.hir_id).first() {
|
||||
field.span.with_lo(attr.span().lo())
|
||||
} else {
|
||||
field.span
|
||||
|
|
|
@ -32,12 +32,7 @@ declare_lint_pass!(InlineFnWithoutBody => [INLINE_FN_WITHOUT_BODY]);
|
|||
impl<'tcx> LateLintPass<'tcx> for InlineFnWithoutBody {
|
||||
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
|
||||
if let TraitItemKind::Fn(_, TraitFn::Required(_)) = item.kind
|
||||
&& let Some(attr) = cx
|
||||
.tcx
|
||||
.hir()
|
||||
.attrs(item.hir_id())
|
||||
.iter()
|
||||
.find(|a| a.has_name(sym::inline))
|
||||
&& let Some(attr) = cx.tcx.hir_attrs(item.hir_id()).iter().find(|a| a.has_name(sym::inline))
|
||||
{
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
|
|
|
@ -206,7 +206,10 @@ impl ItemNameRepetitions {
|
|||
return;
|
||||
}
|
||||
|
||||
let item_name = item.ident.name.as_str();
|
||||
let Some(ident) = item.kind.ident() else {
|
||||
return;
|
||||
};
|
||||
let item_name = ident.name.as_str();
|
||||
for var in def.variants {
|
||||
check_enum_start(cx, item_name, var);
|
||||
check_enum_end(cx, item_name, var);
|
||||
|
@ -278,7 +281,10 @@ impl ItemNameRepetitions {
|
|||
fn check_struct_common_affix(&self, cx: &LateContext<'_>, item: &Item<'_>, fields: &[FieldDef<'_>]) {
|
||||
// if the SyntaxContext of the identifiers of the fields and struct differ dont lint them.
|
||||
// this prevents linting in macros in which the location of the field identifier names differ
|
||||
if !fields.iter().all(|field| item.ident.span.eq_ctxt(field.ident.span)) {
|
||||
if !fields
|
||||
.iter()
|
||||
.all(|field| item.kind.ident().is_some_and(|i| i.span.eq_ctxt(field.ident.span)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -346,14 +352,15 @@ impl ItemNameRepetitions {
|
|||
}
|
||||
|
||||
fn check_struct_name_repetition(&self, cx: &LateContext<'_>, item: &Item<'_>, fields: &[FieldDef<'_>]) {
|
||||
let snake_name = to_snake_case(item.ident.name.as_str());
|
||||
let Some(ident) = item.kind.ident() else { return };
|
||||
let snake_name = to_snake_case(ident.name.as_str());
|
||||
let item_name_words: Vec<&str> = snake_name.split('_').collect();
|
||||
for field in fields {
|
||||
if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(field.def_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if !field.ident.span.eq_ctxt(item.ident.span) {
|
||||
if !field.ident.span.eq_ctxt(ident.span) {
|
||||
// consider linting only if the field identifier has the same SyntaxContext as the item(struct)
|
||||
continue;
|
||||
}
|
||||
|
@ -426,19 +433,23 @@ fn check_enum_end(cx: &LateContext<'_>, item_name: &str, variant: &Variant<'_>)
|
|||
}
|
||||
|
||||
impl LateLintPass<'_> for ItemNameRepetitions {
|
||||
fn check_item_post(&mut self, _cx: &LateContext<'_>, _item: &Item<'_>) {
|
||||
fn check_item_post(&mut self, _cx: &LateContext<'_>, item: &Item<'_>) {
|
||||
let Some(_ident) = item.kind.ident() else { return };
|
||||
|
||||
let last = self.modules.pop();
|
||||
assert!(last.is_some());
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
|
||||
let item_name = item.ident.name.as_str();
|
||||
let Some(ident) = item.kind.ident() else { return };
|
||||
|
||||
let item_name = ident.name.as_str();
|
||||
let item_camel = to_camel_case(item_name);
|
||||
if !item.span.from_expansion() && is_present_in_source(cx, item.span) {
|
||||
if let [.., (mod_name, mod_camel, mod_owner_id)] = &*self.modules {
|
||||
// constants don't have surrounding modules
|
||||
if !mod_camel.is_empty() {
|
||||
if mod_name == &item.ident.name
|
||||
if mod_name == &ident.name
|
||||
&& let ItemKind::Mod(..) = item.kind
|
||||
&& (!self.allow_private_module_inception || cx.tcx.visibility(mod_owner_id.def_id).is_public())
|
||||
{
|
||||
|
@ -467,7 +478,7 @@ impl LateLintPass<'_> for ItemNameRepetitions {
|
|||
Some(c) if is_word_beginning(c) => span_lint(
|
||||
cx,
|
||||
MODULE_NAME_REPETITIONS,
|
||||
item.ident.span,
|
||||
ident.span,
|
||||
"item name starts with its containing module's name",
|
||||
),
|
||||
_ => (),
|
||||
|
@ -479,7 +490,7 @@ impl LateLintPass<'_> for ItemNameRepetitions {
|
|||
span_lint(
|
||||
cx,
|
||||
MODULE_NAME_REPETITIONS,
|
||||
item.ident.span,
|
||||
ident.span,
|
||||
"item name ends with its containing module's name",
|
||||
);
|
||||
}
|
||||
|
@ -490,16 +501,15 @@ impl LateLintPass<'_> for ItemNameRepetitions {
|
|||
|
||||
if span_is_local(item.span) {
|
||||
match item.kind {
|
||||
ItemKind::Enum(def, _) => {
|
||||
ItemKind::Enum(_, def, _) => {
|
||||
self.check_variants(cx, item, &def);
|
||||
},
|
||||
ItemKind::Struct(VariantData::Struct { fields, .. }, _) => {
|
||||
ItemKind::Struct(_, VariantData::Struct { fields, .. }, _) => {
|
||||
self.check_fields(cx, item, fields);
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
self.modules.push((item.ident.name, item_camel, item.owner_id));
|
||||
self.modules.push((ident.name, item_camel, item.owner_id));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ declare_clippy_lint! {
|
|||
declare_lint_pass!(ItemsAfterTestModule => [ITEMS_AFTER_TEST_MODULE]);
|
||||
|
||||
fn cfg_test_module<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool {
|
||||
if let ItemKind::Mod(test_mod) = item.kind
|
||||
if let ItemKind::Mod(_, test_mod) = item.kind
|
||||
&& item.span.hi() == test_mod.spans.inner_span.hi()
|
||||
&& is_cfg_test(cx.tcx, item.hir_id())
|
||||
&& !item.span.from_expansion()
|
||||
|
@ -67,14 +67,20 @@ impl LateLintPass<'_> for ItemsAfterTestModule {
|
|||
let after: Vec<_> = items
|
||||
.filter(|item| {
|
||||
// Ignore the generated test main function
|
||||
!(item.ident.name == sym::main
|
||||
&& item.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::TestHarness))
|
||||
if let ItemKind::Fn { ident, .. } = item.kind
|
||||
&& ident.name == sym::main
|
||||
&& item.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::TestHarness)
|
||||
{
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
if let Some(last) = after.last()
|
||||
&& after.iter().all(|&item| {
|
||||
!matches!(item.kind, ItemKind::Mod(_)) && !item.span.from_expansion() && !is_from_proc_macro(cx, item)
|
||||
!matches!(item.kind, ItemKind::Mod(..)) && !item.span.from_expansion() && !is_from_proc_macro(cx, item)
|
||||
})
|
||||
&& !fulfill_or_allowed(cx, ITEMS_AFTER_TEST_MODULE, after.iter().map(|item| item.hir_id()))
|
||||
{
|
||||
|
|
|
@ -48,7 +48,7 @@ impl_lint_pass!(LargeConstArrays => [LARGE_CONST_ARRAYS]);
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
if let ItemKind::Const(_, generics, _) = &item.kind
|
||||
if let ItemKind::Const(ident, _, generics, _) = &item.kind
|
||||
// Since static items may not have generics, skip generic const items.
|
||||
// FIXME(generic_const_items): I don't think checking `generics.hwcp` suffices as it
|
||||
// doesn't account for empty where-clauses that only consist of keyword `where` IINM.
|
||||
|
@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
|
|||
&& let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
|
||||
&& u128::from(self.maximum_allowed_size) < u128::from(element_count) * u128::from(element_size)
|
||||
{
|
||||
let hi_pos = item.ident.span.lo() - BytePos::from_usize(1);
|
||||
let hi_pos = ident.span.lo() - BytePos::from_usize(1);
|
||||
let sugg_span = Span::new(
|
||||
hi_pos - BytePos::from_usize("const".len()),
|
||||
hi_pos,
|
||||
|
|
|
@ -73,7 +73,7 @@ impl_lint_pass!(LargeEnumVariant => [LARGE_ENUM_VARIANT]);
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &Item<'tcx>) {
|
||||
if let ItemKind::Enum(ref def, _) = item.kind
|
||||
if let ItemKind::Enum(ident, ref def, _) = item.kind
|
||||
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
|
||||
&& let ty::Adt(adt, subst) = ty.kind()
|
||||
&& adt.variants().len() > 1
|
||||
|
@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
|
|||
let mut applicability = Applicability::MaybeIncorrect;
|
||||
if is_copy(cx, ty) || maybe_copy(cx, ty) {
|
||||
diag.span_note(
|
||||
item.ident.span,
|
||||
ident.span,
|
||||
"boxing a variant would require the type no longer be `Copy`",
|
||||
);
|
||||
} else {
|
||||
|
|
|
@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
|
|||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
// Integer modules are "TBD" deprecated, and the contents are too,
|
||||
// so lint on the `use` statement directly.
|
||||
if let ItemKind::Use(path, kind @ (UseKind::Single | UseKind::Glob)) = item.kind
|
||||
if let ItemKind::Use(path, kind @ (UseKind::Single(_) | UseKind::Glob)) = item.kind
|
||||
&& !item.span.in_external_macro(cx.sess().source_map())
|
||||
&& let Some(def_id) = path.res[0].opt_def_id()
|
||||
&& self.msrv.meets(cx, msrvs::NUMERIC_ASSOCIATED_CONSTANTS)
|
||||
|
@ -72,7 +72,9 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
|
|||
"importing a legacy numeric constant"
|
||||
},
|
||||
|diag| {
|
||||
if item.ident.name == kw::Underscore {
|
||||
if let UseKind::Single(ident) = kind
|
||||
&& ident.name == kw::Underscore
|
||||
{
|
||||
diag.help("remove this import");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ use rustc_middle::ty::{self, AssocKind, FnSig, Ty};
|
|||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
use rustc_trait_selection::traits::supertrait_def_ids;
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
@ -123,10 +123,10 @@ declare_lint_pass!(LenZero => [LEN_ZERO, LEN_WITHOUT_IS_EMPTY, COMPARISON_TO_EMP
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for LenZero {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
if let ItemKind::Trait(_, _, _, _, trait_items) = item.kind
|
||||
if let ItemKind::Trait(_, _, ident, _, _, trait_items) = item.kind
|
||||
&& !item.span.from_expansion()
|
||||
{
|
||||
check_trait_items(cx, item, trait_items);
|
||||
check_trait_items(cx, item, ident, trait_items);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,10 +150,10 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
|
|||
let (name, kind) = match cx.tcx.hir_node(ty_hir_id) {
|
||||
Node::ForeignItem(x) => (x.ident.name, "extern type"),
|
||||
Node::Item(x) => match x.kind {
|
||||
ItemKind::Struct(..) => (x.ident.name, "struct"),
|
||||
ItemKind::Enum(..) => (x.ident.name, "enum"),
|
||||
ItemKind::Union(..) => (x.ident.name, "union"),
|
||||
_ => (x.ident.name, "type"),
|
||||
ItemKind::Struct(ident, ..) => (ident.name, "struct"),
|
||||
ItemKind::Enum(ident, ..) => (ident.name, "enum"),
|
||||
ItemKind::Union(ident, ..) => (ident.name, "union"),
|
||||
_ => (x.kind.ident().unwrap().name, "type"),
|
||||
},
|
||||
_ => return,
|
||||
};
|
||||
|
@ -250,7 +250,7 @@ fn span_without_enclosing_paren(cx: &LateContext<'_>, span: Span) -> Span {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items: &[TraitItemRef]) {
|
||||
fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, ident: Ident, trait_items: &[TraitItemRef]) {
|
||||
fn is_named_self(cx: &LateContext<'_>, item: &TraitItemRef, name: Symbol) -> bool {
|
||||
item.ident.name == name
|
||||
&& if let AssocItemKind::Fn { has_self } = item.kind {
|
||||
|
@ -300,7 +300,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items
|
|||
visited_trait.span,
|
||||
format!(
|
||||
"trait `{}` has a `len` method but no (possibly inherited) `is_empty` method",
|
||||
visited_trait.ident.name
|
||||
ident.name
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -79,6 +79,8 @@ struct MutatePairDelegate<'a, 'tcx> {
|
|||
impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
|
||||
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||
|
||||
fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||
|
||||
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) {
|
||||
if bk == ty::BorrowKind::Mutable {
|
||||
if let PlaceBase::Local(id) = cmt.place.base {
|
||||
|
@ -127,7 +129,7 @@ impl BreakAfterExprVisitor {
|
|||
};
|
||||
|
||||
get_enclosing_block(cx, hir_id).is_some_and(|block| {
|
||||
visitor.visit_block(block);
|
||||
let _ = visitor.visit_block(block);
|
||||
visitor.break_after_expr
|
||||
})
|
||||
}
|
||||
|
|
|
@ -177,6 +177,7 @@ fn never_loop_expr<'tcx>(
|
|||
| ExprKind::UnsafeBinderCast(_, e, _) => never_loop_expr(cx, e, local_labels, main_loop_id),
|
||||
ExprKind::Let(let_expr) => never_loop_expr(cx, let_expr.init, local_labels, main_loop_id),
|
||||
ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(cx, es.iter(), local_labels, main_loop_id),
|
||||
ExprKind::Use(expr, _) => never_loop_expr(cx, expr, local_labels, main_loop_id),
|
||||
ExprKind::MethodCall(_, receiver, es, _) => {
|
||||
never_loop_expr_all(cx, once(receiver).chain(es.iter()), local_labels, main_loop_id)
|
||||
},
|
||||
|
|
|
@ -98,7 +98,7 @@ impl LateLintPass<'_> for MacroUseImports {
|
|||
if cx.sess().opts.edition >= Edition::Edition2018
|
||||
&& let hir::ItemKind::Use(path, _kind) = &item.kind
|
||||
&& let hir_id = item.hir_id()
|
||||
&& let attrs = cx.tcx.hir().attrs(hir_id)
|
||||
&& let attrs = cx.tcx.hir_attrs(hir_id)
|
||||
&& let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use))
|
||||
&& let Some(id) = path.res.iter().find_map(|res| match res {
|
||||
Res::Def(DefKind::Mod, id) => Some(id),
|
||||
|
|
|
@ -87,18 +87,18 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
|
|||
}
|
||||
|
||||
match item.kind {
|
||||
ItemKind::Enum(def, _) if def.variants.len() > 1 => {
|
||||
ItemKind::Enum(_, def, _) if def.variants.len() > 1 => {
|
||||
let iter = def.variants.iter().filter_map(|v| {
|
||||
(matches!(v.data, VariantData::Unit(_, _)) && is_doc_hidden(cx.tcx.hir().attrs(v.hir_id)))
|
||||
(matches!(v.data, VariantData::Unit(_, _)) && is_doc_hidden(cx.tcx.hir_attrs(v.hir_id)))
|
||||
.then_some((v.def_id, v.span))
|
||||
});
|
||||
if let Ok((id, span)) = iter.exactly_one()
|
||||
&& !attr::contains_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive)
|
||||
&& !attr::contains_name(cx.tcx.hir_attrs(item.hir_id()), sym::non_exhaustive)
|
||||
{
|
||||
self.potential_enums.push((item.owner_id.def_id, id, item.span, span));
|
||||
}
|
||||
},
|
||||
ItemKind::Struct(variant_data, _) => {
|
||||
ItemKind::Struct(_, variant_data, _) => {
|
||||
let fields = variant_data.fields();
|
||||
let private_fields = fields
|
||||
.iter()
|
||||
|
@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
|
|||
"this seems like a manual implementation of the non-exhaustive pattern",
|
||||
|diag| {
|
||||
if let Some(non_exhaustive) =
|
||||
attr::find_by_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive)
|
||||
attr::find_by_name(cx.tcx.hir_attrs(item.hir_id()), sym::non_exhaustive)
|
||||
{
|
||||
diag.span_note(non_exhaustive.span(), "the struct is already non-exhaustive");
|
||||
} else {
|
||||
|
|
|
@ -99,7 +99,7 @@ where
|
|||
});
|
||||
if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(l), .. })) = e.kind {
|
||||
match captures.get(l) {
|
||||
Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None,
|
||||
Some(CaptureKind::Value | CaptureKind::Use | CaptureKind::Ref(Mutability::Mut)) => return None,
|
||||
Some(CaptureKind::Ref(Mutability::Not)) if binding_ref_mutability == Mutability::Mut => {
|
||||
return None;
|
||||
},
|
||||
|
|
|
@ -42,7 +42,7 @@ pub(super) fn check_match<'tcx>(
|
|||
cx,
|
||||
scrutinee,
|
||||
arms.iter()
|
||||
.map(|arm| (cx.tcx.hir().attrs(arm.hir_id), Some(arm.pat), arm.body, arm.guard)),
|
||||
.map(|arm| (cx.tcx.hir_attrs(arm.hir_id), Some(arm.pat), arm.body, arm.guard)),
|
||||
e,
|
||||
false,
|
||||
)
|
||||
|
|
|
@ -75,7 +75,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
|
|||
HirIdMapEntry::Occupied(entry) => return *entry.get() == b_id,
|
||||
}
|
||||
// the names technically don't have to match; this makes the lint more conservative
|
||||
&& cx.tcx.hir().name(a_id) == cx.tcx.hir().name(b_id)
|
||||
&& cx.tcx.hir_name(a_id) == cx.tcx.hir_name(b_id)
|
||||
&& cx.typeck_results().expr_ty(a) == cx.typeck_results().expr_ty(b)
|
||||
&& pat_contains_local(lhs.pat, a_id)
|
||||
&& pat_contains_local(rhs.pat, b_id)
|
||||
|
|
|
@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_
|
|||
fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool {
|
||||
cx.tcx
|
||||
.hir_parent_id_iter(id)
|
||||
.any(|id| cx.tcx.hir().attrs(id).iter().any(|attr| attr.has_name(sym::cfg)))
|
||||
.any(|id| cx.tcx.hir_attrs(id).iter().any(|attr| attr.has_name(sym::cfg)))
|
||||
}
|
||||
|
||||
/// Similar to [`clippy_utils::expr_or_init`], but does not go up the chain if the initialization
|
||||
|
|
|
@ -147,6 +147,8 @@ impl<'tcx> Delegate<'tcx> for MoveDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||
|
||||
fn borrow(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId, _: BorrowKind) {}
|
||||
|
||||
fn mutate(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||
|
|
|
@ -4731,7 +4731,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
|
|||
}
|
||||
let name = impl_item.ident.name.as_str();
|
||||
let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
|
||||
let item = cx.tcx.hir().expect_item(parent);
|
||||
let item = cx.tcx.hir_expect_item(parent);
|
||||
let self_ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
|
||||
|
||||
let implements_trait = matches!(item.kind, hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }));
|
||||
|
|
|
@ -40,7 +40,7 @@ pub fn check(cx: &LateContext<'_>, call: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<
|
|||
// We've checked that `call` is a call to `Stdin::read_line()` with the right receiver,
|
||||
// now let's check if the first use of the string passed to `::read_line()`
|
||||
// is used for operations that will always fail (e.g. parsing "6\n" into a number)
|
||||
for_each_local_use_after_expr(cx, local_id, call.hir_id, |expr| {
|
||||
let _ = for_each_local_use_after_expr(cx, local_id, call.hir_id, |expr| {
|
||||
if let Some(parent) = get_parent_expr(cx, expr) {
|
||||
let data = if let ExprKind::MethodCall(segment, recv, args, span) = parent.kind {
|
||||
if args.is_empty()
|
||||
|
|
|
@ -182,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
|
|||
}
|
||||
|
||||
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
|
||||
let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID);
|
||||
let attrs = cx.tcx.hir_attrs(hir::CRATE_HIR_ID);
|
||||
self.check_missing_docs_attrs(cx, CRATE_DEF_ID, attrs, cx.tcx.def_span(CRATE_DEF_ID), "the", "crate");
|
||||
}
|
||||
|
||||
|
@ -192,17 +192,17 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
|
|||
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) {
|
||||
match it.kind {
|
||||
hir::ItemKind::Fn { .. } => {
|
||||
hir::ItemKind::Fn { ident, .. } => {
|
||||
// ignore main()
|
||||
if it.ident.name == sym::main {
|
||||
if ident.name == sym::main {
|
||||
let at_root = cx.tcx.local_parent(it.owner_id.def_id) == CRATE_DEF_ID;
|
||||
if at_root {
|
||||
note_prev_span_then_ret!(self.prev_span, it.span);
|
||||
}
|
||||
}
|
||||
},
|
||||
hir::ItemKind::Const(..) => {
|
||||
if it.ident.name == kw::Underscore {
|
||||
hir::ItemKind::Const(ident, ..) => {
|
||||
if ident.name == kw::Underscore {
|
||||
note_prev_span_then_ret!(self.prev_span, it.span);
|
||||
}
|
||||
},
|
||||
|
@ -224,7 +224,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
|
|||
|
||||
let (article, desc) = cx.tcx.article_and_description(it.owner_id.to_def_id());
|
||||
|
||||
let attrs = cx.tcx.hir().attrs(it.hir_id());
|
||||
let attrs = cx.tcx.hir_attrs(it.hir_id());
|
||||
if !is_from_proc_macro(cx, it) {
|
||||
self.check_missing_docs_attrs(cx, it.owner_id.def_id, attrs, it.span, article, desc);
|
||||
}
|
||||
|
@ -234,7 +234,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
|
|||
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx hir::TraitItem<'_>) {
|
||||
let (article, desc) = cx.tcx.article_and_description(trait_item.owner_id.to_def_id());
|
||||
|
||||
let attrs = cx.tcx.hir().attrs(trait_item.hir_id());
|
||||
let attrs = cx.tcx.hir_attrs(trait_item.hir_id());
|
||||
if !is_from_proc_macro(cx, trait_item) {
|
||||
self.check_missing_docs_attrs(cx, trait_item.owner_id.def_id, attrs, trait_item.span, article, desc);
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
|
|||
}
|
||||
|
||||
let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id());
|
||||
let attrs = cx.tcx.hir().attrs(impl_item.hir_id());
|
||||
let attrs = cx.tcx.hir_attrs(impl_item.hir_id());
|
||||
if !is_from_proc_macro(cx, impl_item) {
|
||||
self.check_missing_docs_attrs(cx, impl_item.owner_id.def_id, attrs, impl_item.span, article, desc);
|
||||
}
|
||||
|
@ -261,7 +261,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
|
|||
|
||||
fn check_field_def(&mut self, cx: &LateContext<'tcx>, sf: &'tcx hir::FieldDef<'_>) {
|
||||
if !sf.is_positional() {
|
||||
let attrs = cx.tcx.hir().attrs(sf.hir_id);
|
||||
let attrs = cx.tcx.hir_attrs(sf.hir_id);
|
||||
if !is_from_proc_macro(cx, sf) {
|
||||
self.check_missing_docs_attrs(cx, sf.def_id, attrs, sf.span, "a", "struct field");
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
|
|||
}
|
||||
|
||||
fn check_variant(&mut self, cx: &LateContext<'tcx>, v: &'tcx hir::Variant<'_>) {
|
||||
let attrs = cx.tcx.hir().attrs(v.hir_id);
|
||||
let attrs = cx.tcx.hir_attrs(v.hir_id);
|
||||
if !is_from_proc_macro(cx, v) {
|
||||
self.check_missing_docs_attrs(cx, v.def_id, attrs, v.span, "a", "variant");
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ impl_lint_pass!(ImportRename => [MISSING_ENFORCED_IMPORT_RENAMES]);
|
|||
|
||||
impl LateLintPass<'_> for ImportRename {
|
||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
|
||||
if let ItemKind::Use(path, UseKind::Single) = &item.kind {
|
||||
if let ItemKind::Use(path, UseKind::Single(_)) = &item.kind {
|
||||
for &res in &path.res {
|
||||
if let Res::Def(_, id) = res
|
||||
&& let Some(name) = self.renames.get(&id)
|
||||
|
|
|
@ -226,7 +226,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug {
|
|||
&& should_lint(cx, typeck_results, block)
|
||||
{
|
||||
// we intentionally only lint structs, see lint description
|
||||
if let ItemKind::Struct(data, _) = &self_item.kind {
|
||||
if let ItemKind::Struct(_, data, _) = &self_item.kind {
|
||||
check_struct(cx, typeck_results, block, self_ty, item, data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,10 +98,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
|
|||
match it.kind {
|
||||
hir::ItemKind::Fn { .. } => {
|
||||
let desc = "a function";
|
||||
let attrs = cx.tcx.hir().attrs(it.hir_id());
|
||||
let attrs = cx.tcx.hir_attrs(it.hir_id());
|
||||
check_missing_inline_attrs(cx, attrs, it.span, desc);
|
||||
},
|
||||
hir::ItemKind::Trait(ref _is_auto, ref _unsafe, _generics, _bounds, trait_items) => {
|
||||
hir::ItemKind::Trait(ref _is_auto, ref _unsafe, _ident, _generics, _bounds, trait_items) => {
|
||||
// note: we need to check if the trait is exported so we can't use
|
||||
// `LateLintPass::check_trait_item` here.
|
||||
for tit in trait_items {
|
||||
|
@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
|
|||
// an impl is not provided
|
||||
let desc = "a default trait method";
|
||||
let item = cx.tcx.hir_trait_item(tit.id);
|
||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||
let attrs = cx.tcx.hir_attrs(item.hir_id());
|
||||
check_missing_inline_attrs(cx, attrs, item.span, desc);
|
||||
}
|
||||
},
|
||||
|
@ -168,7 +168,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
|
|||
}
|
||||
}
|
||||
|
||||
let attrs = cx.tcx.hir().attrs(impl_item.hir_id());
|
||||
let attrs = cx.tcx.hir_attrs(impl_item.hir_id());
|
||||
check_missing_inline_attrs(cx, attrs, impl_item.span, desc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -334,7 +334,7 @@ impl<'tcx> Visitor<'tcx> for ReadVisitor<'_, 'tcx> {
|
|||
self.cx,
|
||||
MIXED_READ_WRITE_IN_EXPRESSION,
|
||||
expr.span,
|
||||
format!("unsequenced read of `{}`", self.cx.tcx.hir().name(self.var)),
|
||||
format!("unsequenced read of `{}`", self.cx.tcx.hir_name(self.var)),
|
||||
|diag| {
|
||||
diag.span_note(
|
||||
self.write_expr.span,
|
||||
|
|
|
@ -65,7 +65,7 @@ impl LateLintPass<'_> for NeedlessIf {
|
|||
stmt.span,
|
||||
"this `if` branch is empty",
|
||||
"you can remove it",
|
||||
if cond.can_have_side_effects() || !cx.tcx.hir().attrs(stmt.hir_id).is_empty() {
|
||||
if cond.can_have_side_effects() || !cx.tcx.hir_attrs(stmt.hir_id).is_empty() {
|
||||
// `{ foo }` or `{ foo } && bar` placed into a statement position would be
|
||||
// interpreted as a block statement, force it to be an expression
|
||||
if cond_snippet.starts_with('{') {
|
||||
|
|
|
@ -259,7 +259,7 @@ fn check<'tcx>(
|
|||
binding_id: HirId,
|
||||
) -> Option<()> {
|
||||
let usage = first_usage(cx, binding_id, local_stmt.hir_id, block)?;
|
||||
let binding_name = cx.tcx.hir().opt_name(binding_id)?;
|
||||
let binding_name = cx.tcx.hir_opt_name(binding_id)?;
|
||||
let let_snippet = local_snippet_without_semicolon(cx, local)?;
|
||||
|
||||
match usage.expr.kind {
|
||||
|
|
|
@ -147,7 +147,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
|
|||
// We don't check unsafe functions.
|
||||
return;
|
||||
}
|
||||
let attrs = cx.tcx.hir().attrs(hir_id);
|
||||
let attrs = cx.tcx.hir_attrs(hir_id);
|
||||
if header.abi != ExternAbi::Rust || requires_exact_signature(attrs) {
|
||||
return;
|
||||
}
|
||||
|
@ -396,6 +396,8 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn use_cloned(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId) {}
|
||||
|
||||
#[allow(clippy::if_same_then_else)]
|
||||
fn borrow(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, id: HirId, borrow: ty::BorrowKind) {
|
||||
self.prev_bind = None;
|
||||
|
|
|
@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
|
|||
|
||||
match kind {
|
||||
FnKind::ItemFn(.., header) => {
|
||||
let attrs = cx.tcx.hir().attrs(hir_id);
|
||||
let attrs = cx.tcx.hir_attrs(hir_id);
|
||||
if header.abi != ExternAbi::Rust || requires_exact_signature(attrs) {
|
||||
return;
|
||||
}
|
||||
|
@ -326,6 +326,8 @@ impl<'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt {
|
|||
self.move_common(cmt);
|
||||
}
|
||||
|
||||
fn use_cloned(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId) {}
|
||||
|
||||
fn borrow(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {}
|
||||
|
||||
fn mutate(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId) {}
|
||||
|
|
|
@ -37,12 +37,12 @@ declare_lint_pass!(NoMangleWithRustAbi => [NO_MANGLE_WITH_RUST_ABI]);
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
if let ItemKind::Fn { sig: fn_sig, .. } = &item.kind
|
||||
if let ItemKind::Fn { ident, sig: fn_sig, .. } = &item.kind
|
||||
&& !item.span.from_expansion()
|
||||
{
|
||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||
let attrs = cx.tcx.hir_attrs(item.hir_id());
|
||||
let mut app = Applicability::MaybeIncorrect;
|
||||
let fn_snippet = snippet_with_applicability(cx, fn_sig.span.with_hi(item.ident.span.lo()), "..", &mut app);
|
||||
let fn_snippet = snippet_with_applicability(cx, fn_sig.span.with_hi(ident.span.lo()), "..", &mut app);
|
||||
for attr in attrs {
|
||||
if let Some(ident) = attr.ident()
|
||||
&& ident.name == rustc_span::sym::no_mangle
|
||||
|
|
|
@ -351,7 +351,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
|
|||
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
|
||||
if let ImplItemKind::Const(_, body_id) = &impl_item.kind {
|
||||
let item_def_id = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
|
||||
let item = cx.tcx.hir().expect_item(item_def_id);
|
||||
let item = cx.tcx.hir_expect_item(item_def_id);
|
||||
|
||||
match &item.kind {
|
||||
ItemKind::Impl(Impl {
|
||||
|
|
|
@ -192,7 +192,7 @@ struct LazyInfo {
|
|||
impl LazyInfo {
|
||||
fn from_item(state: &NonStdLazyStatic, cx: &LateContext<'_>, item: &Item<'_>) -> Option<Self> {
|
||||
// Check if item is a `once_cell:sync::Lazy` static.
|
||||
if let ItemKind::Static(ty, _, body_id) = item.kind
|
||||
if let ItemKind::Static(_, ty, _, body_id) = item.kind
|
||||
&& let Some(path_def_id) = path_def_id(cx, ty)
|
||||
&& let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
|
||||
&& state.once_cell_sync_lazy.contains(&path_def_id)
|
||||
|
|
|
@ -112,6 +112,7 @@ fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet {
|
|||
}
|
||||
|
||||
fn consume(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
|
||||
fn use_cloned(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
|
||||
fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
|
||||
fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: HirId) {}
|
||||
fn copy(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
|
||||
|
@ -137,6 +138,7 @@ fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet {
|
|||
}
|
||||
|
||||
fn consume(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
|
||||
fn use_cloned(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
|
||||
fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
|
||||
fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: HirId) {}
|
||||
fn copy(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
|
||||
|
|
|
@ -50,7 +50,7 @@ pub(crate) fn check<'tcx>(
|
|||
// format the suggestion
|
||||
let suggestion = format!(
|
||||
"{}.abs()",
|
||||
sugg::make_assoc(AssocOp::Subtract, &sug_l, &sug_r).maybe_par()
|
||||
sugg::make_assoc(AssocOp::Binary(BinOpKind::Sub), &sug_l, &sug_r).maybe_par()
|
||||
);
|
||||
// spans the lint
|
||||
span_lint_and_then(
|
||||
|
|
|
@ -181,7 +181,7 @@ fn in_impl<'tcx>(
|
|||
) -> Option<(&'tcx rustc_hir::Ty<'tcx>, &'tcx rustc_hir::Ty<'tcx>)> {
|
||||
if let Some(block) = get_enclosing_block(cx, e.hir_id)
|
||||
&& let Some(impl_def_id) = cx.tcx.impl_of_method(block.hir_id.owner.to_def_id())
|
||||
&& let item = cx.tcx.hir().expect_item(impl_def_id.expect_local())
|
||||
&& let item = cx.tcx.hir_expect_item(impl_def_id.expect_local())
|
||||
&& let ItemKind::Impl(item) = &item.kind
|
||||
&& let Some(of_trait) = &item.of_trait
|
||||
&& let Some(seg) = of_trait.path.segments.last()
|
||||
|
@ -200,7 +200,7 @@ fn in_impl<'tcx>(
|
|||
fn are_equal(cx: &LateContext<'_>, middle_ty: Ty<'_>, hir_ty: &rustc_hir::Ty<'_>) -> bool {
|
||||
if let ty::Adt(adt_def, _) = middle_ty.kind()
|
||||
&& let Some(local_did) = adt_def.did().as_local()
|
||||
&& let item = cx.tcx.hir().expect_item(local_did)
|
||||
&& let item = cx.tcx.hir_expect_item(local_did)
|
||||
&& let middle_ty_id = item.owner_id.to_def_id()
|
||||
&& let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind
|
||||
&& let Res::Def(_, hir_ty_id) = path.res
|
||||
|
|
|
@ -185,7 +185,7 @@ fn try_get_option_occurrence<'tcx>(
|
|||
.then_some(())
|
||||
.and_then(|()| none_captures.get(local_id))
|
||||
}) {
|
||||
Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None,
|
||||
Some(CaptureKind::Value | CaptureKind::Use | CaptureKind::Ref(Mutability::Mut)) => return None,
|
||||
Some(CaptureKind::Ref(Mutability::Not)) if as_mut => return None,
|
||||
Some(CaptureKind::Ref(Mutability::Not)) | None => (),
|
||||
}
|
||||
|
|
|
@ -141,7 +141,7 @@ impl PassByRefOrValue {
|
|||
// Gather all the lifetimes found in the output type which may affect whether
|
||||
// `TRIVIALLY_COPY_PASS_BY_REF` should be linted.
|
||||
let mut output_regions = FxHashSet::default();
|
||||
for_each_top_level_late_bound_region(fn_sig.skip_binder().output(), |region| -> ControlFlow<!> {
|
||||
let _ = for_each_top_level_late_bound_region(fn_sig.skip_binder().output(), |region| -> ControlFlow<!> {
|
||||
output_regions.insert(region);
|
||||
ControlFlow::Continue(())
|
||||
});
|
||||
|
@ -280,7 +280,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
|
|||
if header.abi != ExternAbi::Rust {
|
||||
return;
|
||||
}
|
||||
let attrs = cx.tcx.hir().attrs(hir_id);
|
||||
let attrs = cx.tcx.hir_attrs(hir_id);
|
||||
for a in attrs {
|
||||
if let Some(meta_items) = a.meta_item_list() {
|
||||
if a.has_name(sym::proc_macro_derive)
|
||||
|
|
|
@ -58,7 +58,7 @@ impl PubUnderscoreFields {
|
|||
impl<'tcx> LateLintPass<'tcx> for PubUnderscoreFields {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
// This lint only pertains to structs.
|
||||
let ItemKind::Struct(variant_data, _) = &item.kind else {
|
||||
let ItemKind::Struct(_, variant_data, _) = &item.kind else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for PubUnderscoreFields {
|
|||
// Only pertains to fields that start with an underscore, and are public.
|
||||
if field.ident.as_str().starts_with('_') && is_visible(field)
|
||||
// We ignore fields that have `#[doc(hidden)]`.
|
||||
&& !is_doc_hidden(cx.tcx.hir().attrs(field.hir_id))
|
||||
&& !is_doc_hidden(cx.tcx.hir_attrs(field.hir_id))
|
||||
// We ignore fields that are `PhantomData`.
|
||||
&& !is_path_lang_item(cx, field.ty, LangItem::PhantomData)
|
||||
{
|
||||
|
|
|
@ -93,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec {
|
|||
},
|
||||
),
|
||||
VecInitKind::WithExprCapacity(hir_id) => {
|
||||
let e = cx.tcx.hir().expect_expr(hir_id);
|
||||
let e = cx.tcx.hir_expect_expr(hir_id);
|
||||
span_lint_hir_and_then(
|
||||
cx,
|
||||
READ_ZERO_BYTE_VEC,
|
||||
|
|
|
@ -52,7 +52,13 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
|
|||
&& is_not_macro_export(item)
|
||||
&& !item.span.in_external_macro(cx.sess().source_map())
|
||||
{
|
||||
let span = item.span.with_hi(item.ident.span.hi());
|
||||
// FIXME: `DUMMY_SP` isn't right here, because it causes the
|
||||
// resulting span to begin at the start of the file.
|
||||
let span = item.span.with_hi(
|
||||
item.kind
|
||||
.ident()
|
||||
.map_or(rustc_span::DUMMY_SP.hi(), |ident| ident.span.hi()),
|
||||
);
|
||||
let descr = cx.tcx.def_kind(item.owner_id).descr(item.owner_id.to_def_id());
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
|
|
|
@ -74,7 +74,7 @@ fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, spa
|
|||
// We only show this warning for public exported methods.
|
||||
&& cx.effective_visibilities.is_exported(fn_def)
|
||||
// We don't want to emit this lint if the `#[must_use]` attribute is already there.
|
||||
&& !cx.tcx.hir().attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use))
|
||||
&& !cx.tcx.hir_attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use))
|
||||
&& cx.tcx.visibility(fn_def.to_def_id()).is_public()
|
||||
&& let ret_ty = return_ty(cx, owner_id)
|
||||
&& let self_arg = nth_arg(cx, owner_id, 0)
|
||||
|
|
|
@ -231,7 +231,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
|
|||
&& let Some(stmt) = block.stmts.iter().last()
|
||||
&& let StmtKind::Let(local) = &stmt.kind
|
||||
&& local.ty.is_none()
|
||||
&& cx.tcx.hir().attrs(local.hir_id).is_empty()
|
||||
&& cx.tcx.hir_attrs(local.hir_id).is_empty()
|
||||
&& let Some(initexpr) = &local.init
|
||||
&& let PatKind::Binding(_, local_id, _, _) = local.pat.kind
|
||||
&& path_to_local_id(retexpr, local_id)
|
||||
|
@ -401,7 +401,7 @@ fn check_final_expr<'tcx>(
|
|||
// This allows the addition of attributes, like `#[allow]` (See: clippy#9361)
|
||||
// `#[expect(clippy::needless_return)]` needs to be handled separately to
|
||||
// actually fulfill the expectation (clippy::#12998)
|
||||
match cx.tcx.hir().attrs(expr.hir_id) {
|
||||
match cx.tcx.hir_attrs(expr.hir_id) {
|
||||
[] => {},
|
||||
[attr] => {
|
||||
if matches!(Level::from_attr(attr), Some(Level::Expect(_)))
|
||||
|
|
|
@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors {
|
|||
}
|
||||
|
||||
let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
|
||||
let item = cx.tcx.hir().expect_item(parent);
|
||||
let item = cx.tcx.hir_expect_item(parent);
|
||||
let self_ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
|
||||
let ret_ty = return_ty(cx, impl_item.owner_id);
|
||||
|
||||
|
@ -73,7 +73,8 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors {
|
|||
if let Some(self_def) = self_ty.ty_adt_def()
|
||||
&& let Some(self_local_did) = self_def.did().as_local()
|
||||
&& let Node::Item(x) = cx.tcx.hir_node_by_def_id(self_local_did)
|
||||
&& let type_name = x.ident.name.as_str().to_lowercase()
|
||||
&& let Some(type_ident) = x.kind.ident()
|
||||
&& let type_name = type_ident.name.as_str().to_lowercase()
|
||||
&& (impl_item.ident.name.as_str() == type_name
|
||||
|| impl_item.ident.name.as_str().replace('_', "") == type_name)
|
||||
{
|
||||
|
|
|
@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray {
|
|||
}
|
||||
|
||||
fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool {
|
||||
if let ItemKind::Struct(data, _) = &item.kind
|
||||
if let ItemKind::Struct(_, data, _) = &item.kind
|
||||
&& let Some(last_field) = data.fields().last()
|
||||
&& let field_ty = cx.tcx.normalize_erasing_regions(
|
||||
cx.typing_env(),
|
||||
|
|
|
@ -112,7 +112,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
|
|||
// special handling for self trait bounds as these are not considered generics
|
||||
// ie. trait Foo: Display {}
|
||||
if let Item {
|
||||
kind: ItemKind::Trait(_, _, _, bounds, ..),
|
||||
kind: ItemKind::Trait(_, _, _, _, bounds, ..),
|
||||
..
|
||||
} = item
|
||||
{
|
||||
|
@ -133,7 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
|
|||
..
|
||||
}) = segments.first()
|
||||
&& let Some(Node::Item(Item {
|
||||
kind: ItemKind::Trait(_, _, _, self_bounds, _),
|
||||
kind: ItemKind::Trait(_, _, _, _, self_bounds, _),
|
||||
..
|
||||
})) = cx.tcx.hir_get_if_local(*def_id)
|
||||
{
|
||||
|
|
|
@ -447,7 +447,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
|
|||
let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id);
|
||||
|
||||
match item.kind {
|
||||
ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _, _) => self.check_ty(
|
||||
ItemKind::Static(_, ty, _, _) | ItemKind::Const(_, ty, _, _) => self.check_ty(
|
||||
cx,
|
||||
ty,
|
||||
CheckTyContext {
|
||||
|
|
|
@ -381,7 +381,7 @@ impl UnconditionalRecursion {
|
|||
implemented_ty_id,
|
||||
method_span,
|
||||
};
|
||||
walk_body(&mut c, body);
|
||||
let _ = walk_body(&mut c, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -460,7 +460,7 @@ fn block_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
|
|||
}
|
||||
|
||||
fn include_attrs_in_span(cx: &LateContext<'_>, hir_id: HirId, span: Span) -> Span {
|
||||
span.to(cx.tcx.hir().attrs(hir_id).iter().fold(span, |acc, attr| {
|
||||
span.to(cx.tcx.hir_attrs(hir_id).iter().fold(span, |acc, attr| {
|
||||
if attr.is_doc_comment() {
|
||||
return acc;
|
||||
}
|
||||
|
@ -488,7 +488,7 @@ fn item_has_safety_comment(cx: &LateContext<'_>, item: &hir::Item<'_>) -> HasSaf
|
|||
let comment_start = match cx.tcx.parent_hir_node(item.hir_id()) {
|
||||
Node::Crate(parent_mod) => comment_start_before_item_in_mod(cx, parent_mod, parent_mod.spans.inner_span, item),
|
||||
Node::Item(parent_item) => {
|
||||
if let ItemKind::Mod(parent_mod) = &parent_item.kind {
|
||||
if let ItemKind::Mod(_, parent_mod) = &parent_item.kind {
|
||||
comment_start_before_item_in_mod(cx, parent_mod, parent_item.span, item)
|
||||
} else {
|
||||
// Doesn't support impls in this position. Pretend a comment was found.
|
||||
|
@ -643,7 +643,7 @@ fn get_body_search_span(cx: &LateContext<'_>) -> Option<Span> {
|
|||
match parent_node {
|
||||
Node::Crate(mod_) => return Some(mod_.spans.inner_span),
|
||||
Node::Item(hir::Item {
|
||||
kind: ItemKind::Mod(mod_),
|
||||
kind: ItemKind::Mod(_, mod_),
|
||||
span,
|
||||
..
|
||||
}) => {
|
||||
|
|
|
@ -130,9 +130,9 @@ impl LateLintPass<'_> for UnnecessaryBoxReturns {
|
|||
}
|
||||
|
||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
|
||||
let ItemKind::Fn { sig, .. } = &item.kind else {
|
||||
let ItemKind::Fn { ident, sig, .. } = &item.kind else {
|
||||
return;
|
||||
};
|
||||
self.check_fn_item(cx, sig.decl, item.owner_id.def_id, item.ident.name);
|
||||
self.check_fn_item(cx, sig.decl, item.owner_id.def_id, ident.name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
|
|||
return;
|
||||
}
|
||||
let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
|
||||
let parent_item = cx.tcx.hir().expect_item(parent);
|
||||
let parent_item = cx.tcx.hir_expect_item(parent);
|
||||
let assoc_item = cx.tcx.associated_item(impl_item.owner_id);
|
||||
let contains_todo = |cx, body: &'_ Body<'_>| -> bool {
|
||||
clippy_utils::visitors::for_each_expr_without_closures(body.value, |e| {
|
||||
|
|
|
@ -60,9 +60,9 @@ impl_lint_pass!(UnusedTraitNames => [UNUSED_TRAIT_NAMES]);
|
|||
impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
if !item.span.in_external_macro(cx.sess().source_map())
|
||||
&& let ItemKind::Use(path, UseKind::Single) = item.kind
|
||||
&& let ItemKind::Use(path, UseKind::Single(ident)) = item.kind
|
||||
// Ignore imports that already use Underscore
|
||||
&& item.ident.name != kw::Underscore
|
||||
&& ident.name != kw::Underscore
|
||||
// Only check traits
|
||||
&& let Some(Res::Def(DefKind::Trait, _)) = path.res.first()
|
||||
&& cx.tcx.maybe_unused_trait_imports(()).contains(&item.owner_id.def_id)
|
||||
|
@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames {
|
|||
&& self.msrv.meets(cx, msrvs::UNDERSCORE_IMPORTS)
|
||||
&& !is_from_proc_macro(cx, &last_segment.ident)
|
||||
{
|
||||
let complete_span = last_segment.ident.span.to(item.ident.span);
|
||||
let complete_span = last_segment.ident.span.to(ident.span);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
UNUSED_TRAIT_NAMES,
|
||||
|
|
|
@ -230,6 +230,8 @@ impl<'tcx> Delegate<'tcx> for MutationVisitor<'tcx> {
|
|||
|
||||
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||
|
||||
fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||
|
||||
fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
|
||||
}
|
||||
|
||||
|
@ -316,7 +318,7 @@ impl<'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'_, 'tcx> {
|
|||
{
|
||||
if call_to_unwrap == unwrappable.safe_to_unwrap {
|
||||
let is_entire_condition = unwrappable.is_entire_condition;
|
||||
let unwrappable_variable_name = self.cx.tcx.hir().name(unwrappable.local_id);
|
||||
let unwrappable_variable_name = self.cx.tcx.hir_name(unwrappable.local_id);
|
||||
let suggested_pattern = if call_to_unwrap {
|
||||
unwrappable.kind.success_variant_pattern()
|
||||
} else {
|
||||
|
|
|
@ -131,11 +131,11 @@ impl LateLintPass<'_> for UpperCaseAcronyms {
|
|||
return;
|
||||
}
|
||||
match it.kind {
|
||||
ItemKind::TyAlias(..) | ItemKind::Struct(..) | ItemKind::Trait(..) => {
|
||||
check_ident(cx, &it.ident, it.hir_id(), self.upper_case_acronyms_aggressive);
|
||||
ItemKind::TyAlias(ident, ..) | ItemKind::Struct(ident, ..) | ItemKind::Trait(_, _, ident, ..) => {
|
||||
check_ident(cx, &ident, it.hir_id(), self.upper_case_acronyms_aggressive);
|
||||
},
|
||||
ItemKind::Enum(ref enumdef, _) => {
|
||||
check_ident(cx, &it.ident, it.hir_id(), self.upper_case_acronyms_aggressive);
|
||||
ItemKind::Enum(ident, ref enumdef, _) => {
|
||||
check_ident(cx, &ident, it.hir_id(), self.upper_case_acronyms_aggressive);
|
||||
// check enum variants separately because again we only want to lint on private enums and
|
||||
// the fn check_variant does not know about the vis of the enum of its variants
|
||||
enumdef.variants.iter().for_each(|variant| {
|
||||
|
|
|
@ -426,6 +426,11 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
|||
kind!("Tup({elements})");
|
||||
self.slice(elements, |e| self.expr(e));
|
||||
},
|
||||
ExprKind::Use(expr, _) => {
|
||||
bind!(self, expr);
|
||||
kind!("Use({expr})");
|
||||
self.expr(expr);
|
||||
},
|
||||
ExprKind::Binary(op, left, right) => {
|
||||
bind!(self, op, left, right);
|
||||
kind!("Binary({op}, {left}, {right})");
|
||||
|
@ -488,6 +493,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
|||
}) => {
|
||||
let capture_clause = match capture_clause {
|
||||
CaptureBy::Value { .. } => "Value { .. }",
|
||||
CaptureBy::Use { .. } => "Use { .. }",
|
||||
CaptureBy::Ref => "Ref",
|
||||
};
|
||||
|
||||
|
@ -787,7 +793,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn has_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
|
||||
let attrs = cx.tcx.hir().attrs(hir_id);
|
||||
let attrs = cx.tcx.hir_attrs(hir_id);
|
||||
get_attr(cx.sess(), attrs, "author").count() > 0
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,6 @@ impl<'tcx> LateLintPass<'tcx> for DumpHir {
|
|||
}
|
||||
|
||||
fn has_attr(cx: &LateContext<'_>, hir_id: hir::HirId) -> bool {
|
||||
let attrs = cx.tcx.hir().attrs(hir_id);
|
||||
let attrs = cx.tcx.hir_attrs(hir_id);
|
||||
get_attr(cx.sess(), attrs, "dump").count() > 0
|
||||
}
|
||||
|
|
|
@ -44,11 +44,10 @@ impl AlmostStandardFormulation {
|
|||
impl<'tcx> LateLintPass<'tcx> for AlmostStandardFormulation {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
let mut check_next = false;
|
||||
if let ItemKind::Static(ty, Mutability::Not, _) = item.kind {
|
||||
if let ItemKind::Static(_, ty, Mutability::Not, _) = item.kind {
|
||||
let lines = cx
|
||||
.tcx
|
||||
.hir()
|
||||
.attrs(item.hir_id())
|
||||
.hir_attrs(item.hir_id())
|
||||
.iter()
|
||||
.filter_map(|attr| Attribute::doc_str(attr).map(|sym| (sym, attr)));
|
||||
if is_lint_ref_type(cx, ty) {
|
||||
|
|
|
@ -104,7 +104,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
|
|||
return;
|
||||
}
|
||||
|
||||
if let hir::ItemKind::Static(ty, Mutability::Not, body_id) = item.kind {
|
||||
if let hir::ItemKind::Static(ident, ty, Mutability::Not, body_id) = item.kind {
|
||||
if is_lint_ref_type(cx, ty) {
|
||||
check_invalid_clippy_version_attribute(cx, item);
|
||||
|
||||
|
@ -133,10 +133,10 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
|
|||
cx,
|
||||
DEFAULT_LINT,
|
||||
item.span,
|
||||
format!("the lint `{}` has the default lint description", item.ident.name),
|
||||
format!("the lint `{}` has the default lint description", ident.name),
|
||||
);
|
||||
}
|
||||
self.declared_lints.insert(item.ident.name, item.span);
|
||||
self.declared_lints.insert(ident.name, item.span);
|
||||
}
|
||||
}
|
||||
} else if let Some(macro_call) = root_macro_call_first_node(cx, item) {
|
||||
|
@ -247,7 +247,7 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<'
|
|||
/// This function extracts the version value of a `clippy::version` attribute if the given value has
|
||||
/// one
|
||||
pub(super) fn extract_clippy_version_value(cx: &LateContext<'_>, item: &'_ Item<'_>) -> Option<Symbol> {
|
||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||
let attrs = cx.tcx.hir_attrs(item.hir_id());
|
||||
attrs.iter().find_map(|attr| {
|
||||
if let hir::Attribute::Unparsed(attr_kind) = &attr
|
||||
// Identify attribute
|
||||
|
|
|
@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain:
|
|||
|
||||
<!-- begin autogenerated nightly -->
|
||||
```
|
||||
nightly-2025-02-27
|
||||
nightly-2025-03-20
|
||||
```
|
||||
<!-- end autogenerated nightly -->
|
||||
|
||||
|
|
|
@ -364,6 +364,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
|||
generics: lg,
|
||||
contract: lc,
|
||||
body: lb,
|
||||
define_opaque: _,
|
||||
}),
|
||||
Fn(box ast::Fn {
|
||||
defaultness: rd,
|
||||
|
@ -371,6 +372,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
|||
generics: rg,
|
||||
contract: rc,
|
||||
body: rb,
|
||||
define_opaque: _,
|
||||
}),
|
||||
) => {
|
||||
eq_defaultness(*ld, *rd)
|
||||
|
@ -502,6 +504,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
|
|||
generics: lg,
|
||||
contract: lc,
|
||||
body: lb,
|
||||
define_opaque: _,
|
||||
}),
|
||||
Fn(box ast::Fn {
|
||||
defaultness: rd,
|
||||
|
@ -509,6 +512,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
|
|||
generics: rg,
|
||||
contract: rc,
|
||||
body: rb,
|
||||
define_opaque: _,
|
||||
}),
|
||||
) => {
|
||||
eq_defaultness(*ld, *rd)
|
||||
|
@ -567,6 +571,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
|
|||
generics: lg,
|
||||
contract: lc,
|
||||
body: lb,
|
||||
define_opaque: _,
|
||||
}),
|
||||
Fn(box ast::Fn {
|
||||
defaultness: rd,
|
||||
|
@ -574,6 +579,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
|
|||
generics: rg,
|
||||
contract: rc,
|
||||
body: rb,
|
||||
define_opaque: _,
|
||||
}),
|
||||
) => {
|
||||
eq_defaultness(*ld, *rd)
|
||||
|
@ -682,19 +688,20 @@ pub fn eq_generics(l: &Generics, r: &Generics) -> bool {
|
|||
|
||||
pub fn eq_where_predicate(l: &WherePredicate, r: &WherePredicate) -> bool {
|
||||
use WherePredicateKind::*;
|
||||
match (&l.kind, &r.kind) {
|
||||
(BoundPredicate(l), BoundPredicate(r)) => {
|
||||
over(&l.bound_generic_params, &r.bound_generic_params, |l, r| {
|
||||
eq_generic_param(l, r)
|
||||
}) && eq_ty(&l.bounded_ty, &r.bounded_ty)
|
||||
&& over(&l.bounds, &r.bounds, eq_generic_bound)
|
||||
},
|
||||
(RegionPredicate(l), RegionPredicate(r)) => {
|
||||
eq_id(l.lifetime.ident, r.lifetime.ident) && over(&l.bounds, &r.bounds, eq_generic_bound)
|
||||
},
|
||||
(EqPredicate(l), EqPredicate(r)) => eq_ty(&l.lhs_ty, &r.lhs_ty) && eq_ty(&l.rhs_ty, &r.rhs_ty),
|
||||
_ => false,
|
||||
}
|
||||
over(&l.attrs, &r.attrs, eq_attr)
|
||||
&& match (&l.kind, &r.kind) {
|
||||
(BoundPredicate(l), BoundPredicate(r)) => {
|
||||
over(&l.bound_generic_params, &r.bound_generic_params, |l, r| {
|
||||
eq_generic_param(l, r)
|
||||
}) && eq_ty(&l.bounded_ty, &r.bounded_ty)
|
||||
&& over(&l.bounds, &r.bounds, eq_generic_bound)
|
||||
},
|
||||
(RegionPredicate(l), RegionPredicate(r)) => {
|
||||
eq_id(l.lifetime.ident, r.lifetime.ident) && over(&l.bounds, &r.bounds, eq_generic_bound)
|
||||
},
|
||||
(EqPredicate(l), EqPredicate(r)) => eq_ty(&l.lhs_ty, &r.lhs_ty) && eq_ty(&l.rhs_ty, &r.rhs_ty),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eq_use_tree(l: &UseTree, r: &UseTree) -> bool {
|
||||
|
|
|
@ -242,14 +242,14 @@ fn fn_header_search_pat(header: FnHeader) -> Pat {
|
|||
|
||||
fn item_search_pat(item: &Item<'_>) -> (Pat, Pat) {
|
||||
let (start_pat, end_pat) = match &item.kind {
|
||||
ItemKind::ExternCrate(_) => (Pat::Str("extern"), Pat::Str(";")),
|
||||
ItemKind::ExternCrate(..) => (Pat::Str("extern"), Pat::Str(";")),
|
||||
ItemKind::Static(..) => (Pat::Str("static"), Pat::Str(";")),
|
||||
ItemKind::Const(..) => (Pat::Str("const"), Pat::Str(";")),
|
||||
ItemKind::Fn { sig, .. } => (fn_header_search_pat(sig.header), Pat::Str("")),
|
||||
ItemKind::ForeignMod { .. } => (Pat::Str("extern"), Pat::Str("}")),
|
||||
ItemKind::TyAlias(..) => (Pat::Str("type"), Pat::Str(";")),
|
||||
ItemKind::Enum(..) => (Pat::Str("enum"), Pat::Str("}")),
|
||||
ItemKind::Struct(VariantData::Struct { .. }, _) => (Pat::Str("struct"), Pat::Str("}")),
|
||||
ItemKind::Struct(_, VariantData::Struct { .. }, _) => (Pat::Str("struct"), Pat::Str("}")),
|
||||
ItemKind::Struct(..) => (Pat::Str("struct"), Pat::Str(";")),
|
||||
ItemKind::Union(..) => (Pat::Str("union"), Pat::Str("}")),
|
||||
ItemKind::Trait(_, Safety::Unsafe, ..)
|
||||
|
|
|
@ -291,6 +291,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
|
|||
ExprKind::ConstBlock(_)
|
||||
| ExprKind::Array(_)
|
||||
| ExprKind::Tup(_)
|
||||
| ExprKind::Use(..)
|
||||
| ExprKind::Lit(_)
|
||||
| ExprKind::Cast(..)
|
||||
| ExprKind::Type(..)
|
||||
|
|
|
@ -393,6 +393,7 @@ impl HirEqInterExpr<'_, '_, '_> {
|
|||
&& over(lf, rf, |l, r| self.eq_expr_field(l, r))
|
||||
},
|
||||
(&ExprKind::Tup(l_tup), &ExprKind::Tup(r_tup)) => self.eq_exprs(l_tup, r_tup),
|
||||
(&ExprKind::Use(l_expr, _), &ExprKind::Use(r_expr, _)) => self.eq_expr(l_expr, r_expr),
|
||||
(&ExprKind::Type(le, lt), &ExprKind::Type(re, rt)) => self.eq_expr(le, re) && self.eq_ty(lt, rt),
|
||||
(&ExprKind::Unary(l_op, le), &ExprKind::Unary(r_op, re)) => l_op == r_op && self.eq_expr(le, re),
|
||||
(&ExprKind::Yield(le, _), &ExprKind::Yield(re, _)) => return self.eq_expr(le, re),
|
||||
|
@ -425,6 +426,7 @@ impl HirEqInterExpr<'_, '_, '_> {
|
|||
| &ExprKind::Ret(..)
|
||||
| &ExprKind::Struct(..)
|
||||
| &ExprKind::Tup(..)
|
||||
| &ExprKind::Use(..)
|
||||
| &ExprKind::Type(..)
|
||||
| &ExprKind::Unary(..)
|
||||
| &ExprKind::Yield(..)
|
||||
|
@ -1053,6 +1055,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||
ExprKind::Tup(tup) => {
|
||||
self.hash_exprs(tup);
|
||||
},
|
||||
ExprKind::Use(expr, _) => {
|
||||
self.hash_expr(expr);
|
||||
},
|
||||
ExprKind::Unary(lop, le) => {
|
||||
std::mem::discriminant(&lop).hash(&mut self.s);
|
||||
self.hash_expr(le);
|
||||
|
@ -1108,14 +1113,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||
pub fn hash_ty_pat(&mut self, pat: &TyPat<'_>) {
|
||||
std::mem::discriminant(&pat.kind).hash(&mut self.s);
|
||||
match pat.kind {
|
||||
TyPatKind::Range(s, e, i) => {
|
||||
if let Some(s) = s {
|
||||
self.hash_const_arg(s);
|
||||
}
|
||||
if let Some(e) = e {
|
||||
self.hash_const_arg(e);
|
||||
}
|
||||
std::mem::discriminant(&i).hash(&mut self.s);
|
||||
TyPatKind::Range(s, e) => {
|
||||
self.hash_const_arg(s);
|
||||
self.hash_const_arg(e);
|
||||
},
|
||||
TyPatKind::Err(_) => {},
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
// (Currently there is no way to opt into sysroot crates without `extern crate`.)
|
||||
extern crate rustc_abi;
|
||||
extern crate rustc_ast;
|
||||
extern crate rustc_ast_pretty;
|
||||
extern crate rustc_attr_parsing;
|
||||
extern crate rustc_const_eval;
|
||||
extern crate rustc_data_structures;
|
||||
|
@ -645,7 +644,7 @@ fn local_item_children_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, name: Symb
|
|||
let root_mod;
|
||||
let item_kind = match tcx.hir_node_by_def_id(local_id) {
|
||||
Node::Crate(r#mod) => {
|
||||
root_mod = ItemKind::Mod(r#mod);
|
||||
root_mod = ItemKind::Mod(Ident::dummy(), r#mod);
|
||||
&root_mod
|
||||
},
|
||||
Node::Item(item) => &item.kind,
|
||||
|
@ -662,10 +661,13 @@ fn local_item_children_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, name: Symb
|
|||
};
|
||||
|
||||
match item_kind {
|
||||
ItemKind::Mod(r#mod) => r#mod
|
||||
ItemKind::Mod(_, r#mod) => r#mod
|
||||
.item_ids
|
||||
.iter()
|
||||
.filter_map(|&item_id| res(tcx.hir_item(item_id).ident, item_id.owner_id))
|
||||
.filter_map(|&item_id| {
|
||||
let ident = tcx.hir_item(item_id).kind.ident()?;
|
||||
res(ident, item_id.owner_id)
|
||||
})
|
||||
.collect(),
|
||||
ItemKind::Impl(r#impl) => r#impl
|
||||
.items
|
||||
|
@ -1130,6 +1132,7 @@ pub fn can_move_expr_to_closure_no_visit<'tcx>(
|
|||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum CaptureKind {
|
||||
Value,
|
||||
Use,
|
||||
Ref(Mutability),
|
||||
}
|
||||
impl CaptureKind {
|
||||
|
@ -1142,6 +1145,7 @@ impl std::ops::BitOr for CaptureKind {
|
|||
fn bitor(self, rhs: Self) -> Self::Output {
|
||||
match (self, rhs) {
|
||||
(CaptureKind::Value, _) | (_, CaptureKind::Value) => CaptureKind::Value,
|
||||
(CaptureKind::Use, _) | (_, CaptureKind::Use) => CaptureKind::Use,
|
||||
(CaptureKind::Ref(Mutability::Mut), CaptureKind::Ref(_))
|
||||
| (CaptureKind::Ref(_), CaptureKind::Ref(Mutability::Mut)) => CaptureKind::Ref(Mutability::Mut),
|
||||
(CaptureKind::Ref(Mutability::Not), CaptureKind::Ref(Mutability::Not)) => CaptureKind::Ref(Mutability::Not),
|
||||
|
@ -1165,7 +1169,6 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind {
|
|||
pat.each_binding_or_first(&mut |_, id, span, _| match cx
|
||||
.typeck_results()
|
||||
.extract_binding_mode(cx.sess(), id, span)
|
||||
.unwrap()
|
||||
.0
|
||||
{
|
||||
ByRef::No if !is_copy(cx, cx.typeck_results().node_type(id)) => {
|
||||
|
@ -1222,7 +1225,7 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind {
|
|||
},
|
||||
ExprKind::Let(let_expr) => {
|
||||
let mutability = match pat_capture_kind(cx, let_expr.pat) {
|
||||
CaptureKind::Value => Mutability::Not,
|
||||
CaptureKind::Value | CaptureKind::Use => Mutability::Not,
|
||||
CaptureKind::Ref(m) => m,
|
||||
};
|
||||
return CaptureKind::Ref(mutability);
|
||||
|
@ -1231,7 +1234,7 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind {
|
|||
let mut mutability = Mutability::Not;
|
||||
for capture in arms.iter().map(|arm| pat_capture_kind(cx, arm.pat)) {
|
||||
match capture {
|
||||
CaptureKind::Value => break,
|
||||
CaptureKind::Value | CaptureKind::Use => break,
|
||||
CaptureKind::Ref(Mutability::Mut) => mutability = Mutability::Mut,
|
||||
CaptureKind::Ref(Mutability::Not) => (),
|
||||
}
|
||||
|
@ -1241,7 +1244,7 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind {
|
|||
_ => break,
|
||||
},
|
||||
Node::LetStmt(l) => match pat_capture_kind(cx, l.pat) {
|
||||
CaptureKind::Value => break,
|
||||
CaptureKind::Value | CaptureKind::Use => break,
|
||||
capture @ CaptureKind::Ref(_) => return capture,
|
||||
},
|
||||
_ => break,
|
||||
|
@ -1296,6 +1299,7 @@ pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'
|
|||
if !self.locals.contains(&local_id) {
|
||||
let capture = match capture.info.capture_kind {
|
||||
UpvarCapture::ByValue => CaptureKind::Value,
|
||||
UpvarCapture::ByUse => CaptureKind::Use,
|
||||
UpvarCapture::ByRef(kind) => match kind {
|
||||
BorrowKind::Immutable => CaptureKind::Ref(Mutability::Not),
|
||||
BorrowKind::UniqueImmutable | BorrowKind::Mutable => {
|
||||
|
@ -1415,9 +1419,8 @@ pub fn is_in_panic_handler(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
|
|||
pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
|
||||
let parent_id = cx.tcx.hir_get_parent_item(expr.hir_id).def_id;
|
||||
match cx.tcx.hir_node_by_def_id(parent_id) {
|
||||
Node::Item(Item { ident, .. })
|
||||
| Node::TraitItem(TraitItem { ident, .. })
|
||||
| Node::ImplItem(ImplItem { ident, .. }) => Some(ident.name),
|
||||
Node::Item(item) => item.kind.ident().map(|ident| ident.name),
|
||||
Node::TraitItem(TraitItem { ident, .. }) | Node::ImplItem(ImplItem { ident, .. }) => Some(ident.name),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -2035,15 +2038,14 @@ pub fn has_attr(attrs: &[hir::Attribute], symbol: Symbol) -> bool {
|
|||
}
|
||||
|
||||
pub fn has_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
|
||||
find_attr!(cx.tcx.hir().attrs(hir_id), AttributeKind::Repr(..))
|
||||
find_attr!(cx.tcx.hir_attrs(hir_id), AttributeKind::Repr(..))
|
||||
}
|
||||
|
||||
pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool {
|
||||
let map = &tcx.hir();
|
||||
let mut prev_enclosing_node = None;
|
||||
let mut enclosing_node = node;
|
||||
while Some(enclosing_node) != prev_enclosing_node {
|
||||
if has_attr(map.attrs(enclosing_node), symbol) {
|
||||
if has_attr(tcx.hir_attrs(enclosing_node), symbol) {
|
||||
return true;
|
||||
}
|
||||
prev_enclosing_node = Some(enclosing_node);
|
||||
|
@ -2060,7 +2062,7 @@ pub fn in_automatically_derived(tcx: TyCtxt<'_>, id: HirId) -> bool {
|
|||
.filter(|(_, node)| matches!(node, OwnerNode::Item(item) if matches!(item.kind, ItemKind::Impl(_))))
|
||||
.any(|(id, _)| {
|
||||
has_attr(
|
||||
tcx.hir().attrs(tcx.local_def_id_to_hir_id(id.def_id)),
|
||||
tcx.hir_attrs(tcx.local_def_id_to_hir_id(id.def_id)),
|
||||
sym::automatically_derived,
|
||||
)
|
||||
})
|
||||
|
@ -2355,16 +2357,14 @@ pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> {
|
|||
|
||||
pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
|
||||
cx.tcx
|
||||
.hir()
|
||||
.attrs(hir::CRATE_HIR_ID)
|
||||
.hir_attrs(hir::CRATE_HIR_ID)
|
||||
.iter()
|
||||
.any(|attr| attr.name_or_empty() == sym::no_std)
|
||||
}
|
||||
|
||||
pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
|
||||
cx.tcx
|
||||
.hir()
|
||||
.attrs(hir::CRATE_HIR_ID)
|
||||
.hir_attrs(hir::CRATE_HIR_ID)
|
||||
.iter()
|
||||
.any(|attr| attr.name_or_empty() == sym::no_core)
|
||||
}
|
||||
|
@ -2648,18 +2648,17 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Sym
|
|||
for id in tcx.hir_module_free_items(module) {
|
||||
if matches!(tcx.def_kind(id.owner_id), DefKind::Const)
|
||||
&& let item = tcx.hir_item(id)
|
||||
&& let ItemKind::Const(ty, _generics, _body) = item.kind
|
||||
&& let ItemKind::Const(ident, ty, _generics, _body) = item.kind
|
||||
{
|
||||
if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
|
||||
// We could also check for the type name `test::TestDescAndFn`
|
||||
if let Res::Def(DefKind::Struct, _) = path.res {
|
||||
let has_test_marker = tcx
|
||||
.hir()
|
||||
.attrs(item.hir_id())
|
||||
.hir_attrs(item.hir_id())
|
||||
.iter()
|
||||
.any(|a| a.has_name(sym::rustc_test_marker));
|
||||
if has_test_marker {
|
||||
names.push(item.ident.name);
|
||||
names.push(ident.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2683,10 +2682,10 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool {
|
|||
// function scope
|
||||
.any(|(_id, node)| {
|
||||
if let Node::Item(item) = node {
|
||||
if let ItemKind::Fn { .. } = item.kind {
|
||||
if let ItemKind::Fn { ident, .. } = item.kind {
|
||||
// Note that we have sorted the item names in the visitor,
|
||||
// so the binary_search gets the same as `contains`, but faster.
|
||||
return names.binary_search(&item.ident.name).is_ok();
|
||||
return names.binary_search(&ident.name).is_ok();
|
||||
}
|
||||
}
|
||||
false
|
||||
|
@ -2699,7 +2698,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool {
|
|||
/// This only checks directly applied attributes, to see if a node is inside a `#[cfg(test)]` parent
|
||||
/// use [`is_in_cfg_test`]
|
||||
pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool {
|
||||
tcx.hir().attrs(id).iter().any(|attr| {
|
||||
tcx.hir_attrs(id).iter().any(|attr| {
|
||||
if attr.has_name(sym::cfg)
|
||||
&& let Some(items) = attr.meta_item_list()
|
||||
&& let [item] = &*items
|
||||
|
@ -2724,12 +2723,10 @@ pub fn is_in_test(tcx: TyCtxt<'_>, hir_id: HirId) -> bool {
|
|||
|
||||
/// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied.
|
||||
pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
||||
let hir = tcx.hir();
|
||||
|
||||
tcx.has_attr(def_id, sym::cfg)
|
||||
|| tcx
|
||||
.hir_parent_iter(tcx.local_def_id_to_hir_id(def_id))
|
||||
.flat_map(|(parent_id, _)| hir.attrs(parent_id))
|
||||
.flat_map(|(parent_id, _)| tcx.hir_attrs(parent_id))
|
||||
.any(|attr| attr.has_name(sym::cfg))
|
||||
}
|
||||
|
||||
|
@ -3503,7 +3500,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
|
|||
// a::b::c ::d::sym refers to
|
||||
// e::f::sym:: ::
|
||||
// result should be super::super::super::super::e::f
|
||||
if let DefPathData::TypeNs(s) = l {
|
||||
if let DefPathData::TypeNs(Some(s)) = l {
|
||||
path.push(s.to_string());
|
||||
}
|
||||
if let DefPathData::TypeNs(_) = r {
|
||||
|
@ -3514,7 +3511,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
|
|||
// a::b::sym:: :: refers to
|
||||
// c::d::e ::f::sym
|
||||
// when looking at `f`
|
||||
Left(DefPathData::TypeNs(sym)) => path.push(sym.to_string()),
|
||||
Left(DefPathData::TypeNs(Some(sym))) => path.push(sym.to_string()),
|
||||
// consider:
|
||||
// a::b::c ::d::sym refers to
|
||||
// e::f::sym:: ::
|
||||
|
@ -3528,7 +3525,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
|
|||
// `super` chain would be too long, just use the absolute path instead
|
||||
once(String::from("crate"))
|
||||
.chain(to.data.iter().filter_map(|el| {
|
||||
if let DefPathData::TypeNs(sym) = el.data {
|
||||
if let DefPathData::TypeNs(Some(sym)) = el.data {
|
||||
Some(sym.to_string())
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#![allow(clippy::similar_names)] // `expr` and `expn`
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, OnceLock};
|
||||
|
||||
use crate::get_unique_attr;
|
||||
use crate::visitors::{Descend, for_each_expr_without_closures};
|
||||
|
@ -8,7 +8,6 @@ use crate::visitors::{Descend, for_each_expr_without_closures};
|
|||
use arrayvec::ArrayVec;
|
||||
use rustc_ast::{FormatArgs, FormatArgument, FormatPlaceholder};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync::OnceLock;
|
||||
use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_span::def_id::DefId;
|
||||
|
|
|
@ -6,8 +6,7 @@ use rustc_index::bit_set::DenseBitSet;
|
|||
use rustc_lint::LateContext;
|
||||
use rustc_middle::mir::visit::Visitor as _;
|
||||
use rustc_middle::mir::{self, Mutability};
|
||||
use rustc_middle::ty::visit::TypeVisitor;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitor};
|
||||
use rustc_mir_dataflow::impls::MaybeStorageLive;
|
||||
use rustc_mir_dataflow::{Analysis, ResultsCursor};
|
||||
use std::borrow::Cow;
|
||||
|
|
|
@ -109,7 +109,7 @@ impl Msrv {
|
|||
let start = cx.last_node_with_lint_attrs;
|
||||
if let Some(msrv_attr) = once(start)
|
||||
.chain(cx.tcx.hir_parent_id_iter(start))
|
||||
.find_map(|id| parse_attrs(cx.tcx.sess, cx.tcx.hir().attrs(id)))
|
||||
.find_map(|id| parse_attrs(cx.tcx.sess, cx.tcx.hir_attrs(id)))
|
||||
{
|
||||
return Some(msrv_attr);
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@
|
|||
use crate::source::{snippet, snippet_opt, snippet_with_applicability, snippet_with_context};
|
||||
use crate::ty::expr_sig;
|
||||
use crate::{get_parent_expr_for_hir, higher};
|
||||
use rustc_ast::ast;
|
||||
use rustc_ast::util::parser::AssocOp;
|
||||
use rustc_ast::{ast, token};
|
||||
use rustc_ast_pretty::pprust::token_kind_to_string;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{Closure, ExprKind, HirId, MutTy, TyKind};
|
||||
|
@ -114,10 +113,7 @@ impl<'a> Sugg<'a> {
|
|||
/// function variants of `Sugg`, since these use different snippet functions.
|
||||
fn hir_from_snippet(expr: &hir::Expr<'_>, mut get_snippet: impl FnMut(Span) -> Cow<'a, str>) -> Self {
|
||||
if let Some(range) = higher::Range::hir(expr) {
|
||||
let op = match range.limits {
|
||||
ast::RangeLimits::HalfOpen => AssocOp::DotDot,
|
||||
ast::RangeLimits::Closed => AssocOp::DotDotEq,
|
||||
};
|
||||
let op = AssocOp::Range(range.limits);
|
||||
let start = range.start.map_or("".into(), |expr| get_snippet(expr.span));
|
||||
let end = range.end.map_or("".into(), |expr| get_snippet(expr.span));
|
||||
|
||||
|
@ -151,6 +147,7 @@ impl<'a> Sugg<'a> {
|
|||
| ExprKind::Become(..)
|
||||
| ExprKind::Struct(..)
|
||||
| ExprKind::Tup(..)
|
||||
| ExprKind::Use(..)
|
||||
| ExprKind::Err(_)
|
||||
| ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(get_snippet(expr.span)),
|
||||
ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet),
|
||||
|
@ -158,16 +155,16 @@ impl<'a> Sugg<'a> {
|
|||
Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span))
|
||||
},
|
||||
ExprKind::AssignOp(op, lhs, rhs) => {
|
||||
Sugg::BinOp(hirbinop2assignop(op), get_snippet(lhs.span), get_snippet(rhs.span))
|
||||
Sugg::BinOp(AssocOp::AssignOp(op.node), get_snippet(lhs.span), get_snippet(rhs.span))
|
||||
},
|
||||
ExprKind::Binary(op, lhs, rhs) => Sugg::BinOp(
|
||||
AssocOp::from_ast_binop(op.node),
|
||||
AssocOp::Binary(op.node),
|
||||
get_snippet(lhs.span),
|
||||
get_snippet(rhs.span),
|
||||
),
|
||||
ExprKind::Cast(lhs, ty) |
|
||||
//FIXME(chenyukang), remove this after type ascription is removed from AST
|
||||
ExprKind::Type(lhs, ty) => Sugg::BinOp(AssocOp::As, get_snippet(lhs.span), get_snippet(ty.span)),
|
||||
ExprKind::Type(lhs, ty) => Sugg::BinOp(AssocOp::Cast, get_snippet(lhs.span), get_snippet(ty.span)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,8 +176,6 @@ impl<'a> Sugg<'a> {
|
|||
ctxt: SyntaxContext,
|
||||
app: &mut Applicability,
|
||||
) -> Self {
|
||||
use rustc_ast::ast::RangeLimits;
|
||||
|
||||
let mut snippet = |span: Span| snippet_with_context(cx, span, ctxt, default, app).0;
|
||||
|
||||
match expr.kind {
|
||||
|
@ -223,19 +218,15 @@ impl<'a> Sugg<'a> {
|
|||
| ast::ExprKind::Try(..)
|
||||
| ast::ExprKind::TryBlock(..)
|
||||
| ast::ExprKind::Tup(..)
|
||||
| ast::ExprKind::Use(..)
|
||||
| ast::ExprKind::Array(..)
|
||||
| ast::ExprKind::While(..)
|
||||
| ast::ExprKind::Await(..)
|
||||
| ast::ExprKind::Err(_)
|
||||
| ast::ExprKind::Dummy
|
||||
| ast::ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(snippet(expr.span)),
|
||||
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp(
|
||||
AssocOp::DotDot,
|
||||
lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)),
|
||||
rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)),
|
||||
),
|
||||
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::Closed) => Sugg::BinOp(
|
||||
AssocOp::DotDotEq,
|
||||
ast::ExprKind::Range(ref lhs, ref rhs, limits) => Sugg::BinOp(
|
||||
AssocOp::Range(limits),
|
||||
lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)),
|
||||
rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)),
|
||||
),
|
||||
|
@ -245,19 +236,19 @@ impl<'a> Sugg<'a> {
|
|||
snippet(rhs.span),
|
||||
),
|
||||
ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => Sugg::BinOp(
|
||||
astbinop2assignop(op),
|
||||
AssocOp::AssignOp(op.node),
|
||||
snippet(lhs.span),
|
||||
snippet(rhs.span),
|
||||
),
|
||||
ast::ExprKind::Binary(op, ref lhs, ref rhs) => Sugg::BinOp(
|
||||
AssocOp::from_ast_binop(op.node),
|
||||
AssocOp::Binary(op.node),
|
||||
snippet(lhs.span),
|
||||
snippet(rhs.span),
|
||||
),
|
||||
ast::ExprKind::Cast(ref lhs, ref ty) |
|
||||
//FIXME(chenyukang), remove this after type ascription is removed from AST
|
||||
ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp(
|
||||
AssocOp::As,
|
||||
AssocOp::Cast,
|
||||
snippet(lhs.span),
|
||||
snippet(ty.span),
|
||||
),
|
||||
|
@ -276,7 +267,7 @@ impl<'a> Sugg<'a> {
|
|||
|
||||
/// Convenience method to create the `<lhs> as <rhs>` suggestion.
|
||||
pub fn as_ty<R: Display>(self, rhs: R) -> Sugg<'static> {
|
||||
make_assoc(AssocOp::As, &self, &Sugg::NonParen(rhs.to_string().into()))
|
||||
make_assoc(AssocOp::Cast, &self, &Sugg::NonParen(rhs.to_string().into()))
|
||||
}
|
||||
|
||||
/// Convenience method to create the `&<expr>` suggestion.
|
||||
|
@ -327,11 +318,8 @@ impl<'a> Sugg<'a> {
|
|||
|
||||
/// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>`
|
||||
/// suggestion.
|
||||
pub fn range(self, end: &Self, limit: ast::RangeLimits) -> Sugg<'static> {
|
||||
match limit {
|
||||
ast::RangeLimits::HalfOpen => make_assoc(AssocOp::DotDot, &self, end),
|
||||
ast::RangeLimits::Closed => make_assoc(AssocOp::DotDotEq, &self, end),
|
||||
}
|
||||
pub fn range(self, end: &Self, limits: ast::RangeLimits) -> Sugg<'static> {
|
||||
make_assoc(AssocOp::Range(limits), &self, end)
|
||||
}
|
||||
|
||||
/// Adds parentheses to any expression that might need them. Suitable to the
|
||||
|
@ -367,33 +355,11 @@ impl<'a> Sugg<'a> {
|
|||
/// Generates a string from the operator and both sides.
|
||||
fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String {
|
||||
match op {
|
||||
AssocOp::Add
|
||||
| AssocOp::Subtract
|
||||
| AssocOp::Multiply
|
||||
| AssocOp::Divide
|
||||
| AssocOp::Modulus
|
||||
| AssocOp::LAnd
|
||||
| AssocOp::LOr
|
||||
| AssocOp::BitXor
|
||||
| AssocOp::BitAnd
|
||||
| AssocOp::BitOr
|
||||
| AssocOp::ShiftLeft
|
||||
| AssocOp::ShiftRight
|
||||
| AssocOp::Equal
|
||||
| AssocOp::Less
|
||||
| AssocOp::LessEqual
|
||||
| AssocOp::NotEqual
|
||||
| AssocOp::Greater
|
||||
| AssocOp::GreaterEqual => {
|
||||
format!("{lhs} {} {rhs}", op.to_ast_binop().expect("Those are AST ops").as_str())
|
||||
},
|
||||
AssocOp::Binary(op) => format!("{lhs} {} {rhs}", op.as_str()),
|
||||
AssocOp::Assign => format!("{lhs} = {rhs}"),
|
||||
AssocOp::AssignOp(op) => {
|
||||
format!("{lhs} {}= {rhs}", token_kind_to_string(&token::BinOp(op)))
|
||||
},
|
||||
AssocOp::As => format!("{lhs} as {rhs}"),
|
||||
AssocOp::DotDot => format!("{lhs}..{rhs}"),
|
||||
AssocOp::DotDotEq => format!("{lhs}..={rhs}"),
|
||||
AssocOp::AssignOp(op) => format!("{lhs} {}= {rhs}", op.as_str()),
|
||||
AssocOp::Cast => format!("{lhs} as {rhs}"),
|
||||
AssocOp::Range(limits) => format!("{lhs}{}{rhs}", limits.as_str()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -468,7 +434,7 @@ impl Neg for Sugg<'_> {
|
|||
type Output = Sugg<'static>;
|
||||
fn neg(self) -> Sugg<'static> {
|
||||
match &self {
|
||||
Self::BinOp(AssocOp::As, ..) => Sugg::MaybeParen(format!("-({self})").into()),
|
||||
Self::BinOp(AssocOp::Cast, ..) => Sugg::MaybeParen(format!("-({self})").into()),
|
||||
_ => make_unop("-", self),
|
||||
}
|
||||
}
|
||||
|
@ -477,16 +443,17 @@ impl Neg for Sugg<'_> {
|
|||
impl<'a> Not for Sugg<'a> {
|
||||
type Output = Sugg<'a>;
|
||||
fn not(self) -> Sugg<'a> {
|
||||
use AssocOp::{Equal, Greater, GreaterEqual, Less, LessEqual, NotEqual};
|
||||
use AssocOp::Binary;
|
||||
use ast::BinOpKind::{Eq, Ge, Gt, Le, Lt, Ne};
|
||||
|
||||
if let Sugg::BinOp(op, lhs, rhs) = self {
|
||||
let to_op = match op {
|
||||
Equal => NotEqual,
|
||||
NotEqual => Equal,
|
||||
Less => GreaterEqual,
|
||||
GreaterEqual => Less,
|
||||
Greater => LessEqual,
|
||||
LessEqual => Greater,
|
||||
Binary(Eq) => Binary(Ne),
|
||||
Binary(Ne) => Binary(Eq),
|
||||
Binary(Lt) => Binary(Ge),
|
||||
Binary(Ge) => Binary(Lt),
|
||||
Binary(Gt) => Binary(Le),
|
||||
Binary(Le) => Binary(Gt),
|
||||
_ => return make_unop("!", Sugg::BinOp(op, lhs, rhs)),
|
||||
};
|
||||
Sugg::BinOp(to_op, lhs, rhs)
|
||||
|
@ -538,7 +505,7 @@ pub fn make_unop(op: &str, expr: Sugg<'_>) -> Sugg<'static> {
|
|||
pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> {
|
||||
/// Returns `true` if the operator is a shift operator `<<` or `>>`.
|
||||
fn is_shift(op: AssocOp) -> bool {
|
||||
matches!(op, AssocOp::ShiftLeft | AssocOp::ShiftRight)
|
||||
matches!(op, AssocOp::Binary(ast::BinOpKind::Shl | ast::BinOpKind::Shr))
|
||||
}
|
||||
|
||||
/// Returns `true` if the operator is an arithmetic operator
|
||||
|
@ -546,7 +513,13 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static>
|
|||
fn is_arith(op: AssocOp) -> bool {
|
||||
matches!(
|
||||
op,
|
||||
AssocOp::Add | AssocOp::Subtract | AssocOp::Multiply | AssocOp::Divide | AssocOp::Modulus
|
||||
AssocOp::Binary(
|
||||
ast::BinOpKind::Add
|
||||
| ast::BinOpKind::Sub
|
||||
| ast::BinOpKind::Mul
|
||||
| ast::BinOpKind::Div
|
||||
| ast::BinOpKind::Rem
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -578,9 +551,9 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static>
|
|||
Sugg::BinOp(op, lhs.into(), rhs.into())
|
||||
}
|
||||
|
||||
/// Convenience wrapper around `make_assoc` and `AssocOp::from_ast_binop`.
|
||||
/// Convenience wrapper around `make_assoc` and `AssocOp::Binary`.
|
||||
pub fn make_binop(op: ast::BinOpKind, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> {
|
||||
make_assoc(AssocOp::from_ast_binop(op), lhs, rhs)
|
||||
make_assoc(AssocOp::Binary(op), lhs, rhs)
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
|
@ -605,69 +578,17 @@ enum Associativity {
|
|||
/// associative.
|
||||
#[must_use]
|
||||
fn associativity(op: AssocOp) -> Associativity {
|
||||
use rustc_ast::util::parser::AssocOp::{
|
||||
Add, As, Assign, AssignOp, BitAnd, BitOr, BitXor, Divide, DotDot, DotDotEq, Equal, Greater, GreaterEqual, LAnd,
|
||||
LOr, Less, LessEqual, Modulus, Multiply, NotEqual, ShiftLeft, ShiftRight, Subtract,
|
||||
};
|
||||
use ast::BinOpKind::{Add, And, BitAnd, BitOr, BitXor, Div, Eq, Ge, Gt, Le, Lt, Mul, Ne, Or, Rem, Shl, Shr, Sub};
|
||||
use rustc_ast::util::parser::AssocOp::{Assign, AssignOp, Binary, Cast, Range};
|
||||
|
||||
match op {
|
||||
Assign | AssignOp(_) => Associativity::Right,
|
||||
Add | BitAnd | BitOr | BitXor | LAnd | LOr | Multiply | As => Associativity::Both,
|
||||
Divide | Equal | Greater | GreaterEqual | Less | LessEqual | Modulus | NotEqual | ShiftLeft | ShiftRight
|
||||
| Subtract => Associativity::Left,
|
||||
DotDot | DotDotEq => Associativity::None,
|
||||
Binary(Add | BitAnd | BitOr | BitXor | And | Or | Mul) | Cast => Associativity::Both,
|
||||
Binary(Div | Eq | Gt | Ge | Lt | Le | Rem | Ne | Shl | Shr | Sub) => Associativity::Left,
|
||||
Range(_) => Associativity::None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a `hir::BinOp` to the corresponding assigning binary operator.
|
||||
fn hirbinop2assignop(op: hir::BinOp) -> AssocOp {
|
||||
use rustc_ast::token::BinOpToken::{And, Caret, Minus, Or, Percent, Plus, Shl, Shr, Slash, Star};
|
||||
|
||||
AssocOp::AssignOp(match op.node {
|
||||
hir::BinOpKind::Add => Plus,
|
||||
hir::BinOpKind::BitAnd => And,
|
||||
hir::BinOpKind::BitOr => Or,
|
||||
hir::BinOpKind::BitXor => Caret,
|
||||
hir::BinOpKind::Div => Slash,
|
||||
hir::BinOpKind::Mul => Star,
|
||||
hir::BinOpKind::Rem => Percent,
|
||||
hir::BinOpKind::Shl => Shl,
|
||||
hir::BinOpKind::Shr => Shr,
|
||||
hir::BinOpKind::Sub => Minus,
|
||||
|
||||
hir::BinOpKind::And
|
||||
| hir::BinOpKind::Eq
|
||||
| hir::BinOpKind::Ge
|
||||
| hir::BinOpKind::Gt
|
||||
| hir::BinOpKind::Le
|
||||
| hir::BinOpKind::Lt
|
||||
| hir::BinOpKind::Ne
|
||||
| hir::BinOpKind::Or => panic!("This operator does not exist"),
|
||||
})
|
||||
}
|
||||
|
||||
/// Converts an `ast::BinOp` to the corresponding assigning binary operator.
|
||||
fn astbinop2assignop(op: ast::BinOp) -> AssocOp {
|
||||
use rustc_ast::ast::BinOpKind::{
|
||||
Add, And, BitAnd, BitOr, BitXor, Div, Eq, Ge, Gt, Le, Lt, Mul, Ne, Or, Rem, Shl, Shr, Sub,
|
||||
};
|
||||
use rustc_ast::token::BinOpToken;
|
||||
|
||||
AssocOp::AssignOp(match op.node {
|
||||
Add => BinOpToken::Plus,
|
||||
BitAnd => BinOpToken::And,
|
||||
BitOr => BinOpToken::Or,
|
||||
BitXor => BinOpToken::Caret,
|
||||
Div => BinOpToken::Slash,
|
||||
Mul => BinOpToken::Star,
|
||||
Rem => BinOpToken::Percent,
|
||||
Shl => BinOpToken::Shl,
|
||||
Shr => BinOpToken::Shr,
|
||||
Sub => BinOpToken::Minus,
|
||||
And | Eq | Ge | Gt | Le | Lt | Ne | Or => panic!("This operator does not exist"),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the indentation before `span` if there are nothing but `[ \t]`
|
||||
/// before it on its line.
|
||||
fn indentation<T: LintContext>(cx: &T, span: Span) -> Option<String> {
|
||||
|
@ -914,6 +835,8 @@ impl<'tcx> DerefDelegate<'_, 'tcx> {
|
|||
impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
|
||||
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||
|
||||
fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||
|
||||
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {
|
||||
if let PlaceBase::Local(id) = cmt.place.base {
|
||||
let map = self.cx.tcx.hir();
|
||||
|
@ -922,7 +845,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
|
|||
let mut start_snip = snippet_with_applicability(self.cx, start_span, "..", &mut self.applicability);
|
||||
|
||||
// identifier referring to the variable currently triggered (i.e.: `fp`)
|
||||
let ident_str = map.name(id).to_string();
|
||||
let ident_str = self.cx.tcx.hir_name(id).to_string();
|
||||
// full identifier that includes projection (i.e.: `fp.field`)
|
||||
let ident_str_with_proj = snippet(self.cx, span, "..").to_string();
|
||||
|
||||
|
@ -951,7 +874,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
|
|||
// item is used in a call
|
||||
// i.e.: `Call`: `|x| please(x)` or `MethodCall`: `|x| [1, 2, 3].contains(x)`
|
||||
ExprKind::Call(_, call_args) | ExprKind::MethodCall(_, _, call_args, _) => {
|
||||
let expr = self.cx.tcx.hir().expect_expr(cmt.hir_id);
|
||||
let expr = self.cx.tcx.hir_expect_expr(cmt.hir_id);
|
||||
let arg_ty_kind = self.cx.typeck_results().expr_ty(expr).kind();
|
||||
|
||||
if matches!(arg_ty_kind, ty::Ref(_, _, Mutability::Not)) {
|
||||
|
@ -1069,6 +992,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
|
|||
mod test {
|
||||
use super::Sugg;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::util::parser::AssocOp;
|
||||
use std::borrow::Cow;
|
||||
|
||||
|
@ -1086,15 +1010,15 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn binop_maybe_par() {
|
||||
let sugg = Sugg::BinOp(AssocOp::Add, "1".into(), "1".into());
|
||||
let sugg = Sugg::BinOp(AssocOp::Binary(ast::BinOpKind::Add), "1".into(), "1".into());
|
||||
assert_eq!("(1 + 1)", sugg.maybe_par().to_string());
|
||||
|
||||
let sugg = Sugg::BinOp(AssocOp::Add, "(1 + 1)".into(), "(1 + 1)".into());
|
||||
let sugg = Sugg::BinOp(AssocOp::Binary(ast::BinOpKind::Add), "(1 + 1)".into(), "(1 + 1)".into());
|
||||
assert_eq!("((1 + 1) + (1 + 1))", sugg.maybe_par().to_string());
|
||||
}
|
||||
#[test]
|
||||
fn not_op() {
|
||||
use AssocOp::{Add, Equal, Greater, GreaterEqual, LAnd, LOr, Less, LessEqual, NotEqual};
|
||||
use ast::BinOpKind::{Add, And, Eq, Ge, Gt, Le, Lt, Ne, Or};
|
||||
|
||||
fn test_not(op: AssocOp, correct: &str) {
|
||||
let sugg = Sugg::BinOp(op, "x".into(), "y".into());
|
||||
|
@ -1102,16 +1026,16 @@ mod test {
|
|||
}
|
||||
|
||||
// Invert the comparison operator.
|
||||
test_not(Equal, "x != y");
|
||||
test_not(NotEqual, "x == y");
|
||||
test_not(Less, "x >= y");
|
||||
test_not(LessEqual, "x > y");
|
||||
test_not(Greater, "x <= y");
|
||||
test_not(GreaterEqual, "x < y");
|
||||
test_not(AssocOp::Binary(Eq), "x != y");
|
||||
test_not(AssocOp::Binary(Ne), "x == y");
|
||||
test_not(AssocOp::Binary(Lt), "x >= y");
|
||||
test_not(AssocOp::Binary(Le), "x > y");
|
||||
test_not(AssocOp::Binary(Gt), "x <= y");
|
||||
test_not(AssocOp::Binary(Ge), "x < y");
|
||||
|
||||
// Other operators are inverted like !(..).
|
||||
test_not(Add, "!(x + y)");
|
||||
test_not(LAnd, "!(x && y)");
|
||||
test_not(LOr, "!(x || y)");
|
||||
test_not(AssocOp::Binary(Add), "!(x + y)");
|
||||
test_not(AssocOp::Binary(And), "!(x && y)");
|
||||
test_not(AssocOp::Binary(Or), "!(x || y)");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ use crate::{def_path_def_ids, match_def_path, path_res};
|
|||
mod type_certainty;
|
||||
pub use type_certainty::expr_type_is_certain;
|
||||
|
||||
/// Lower a [`hir::Ty`] to a [`rustc_middle::Ty`].
|
||||
/// Lower a [`hir::Ty`] to a [`rustc_middle::ty::Ty`].
|
||||
pub fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
|
||||
cx.maybe_typeck_results()
|
||||
.and_then(|results| {
|
||||
|
|
|
@ -66,6 +66,8 @@ impl MutVarsDelegate {
|
|||
impl<'tcx> Delegate<'tcx> for MutVarsDelegate {
|
||||
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||
|
||||
fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||
|
||||
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, bk: ty::BorrowKind) {
|
||||
if bk == ty::BorrowKind::Mutable {
|
||||
self.update(cmt);
|
||||
|
|
|
@ -648,6 +648,9 @@ pub fn for_each_unconsumed_temporary<'tcx, B>(
|
|||
helper(typeck, true, arg, f)?;
|
||||
}
|
||||
},
|
||||
ExprKind::Use(expr, _) => {
|
||||
helper(typeck, true, expr, f)?;
|
||||
},
|
||||
ExprKind::Index(borrowed, consumed, _)
|
||||
| ExprKind::Assign(borrowed, consumed, _)
|
||||
| ExprKind::AssignOp(_, borrowed, consumed) => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[toolchain]
|
||||
# begin autogenerated nightly
|
||||
channel = "nightly-2025-02-27"
|
||||
channel = "nightly-2025-03-20"
|
||||
# end autogenerated nightly
|
||||
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
||||
profile = "minimal"
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
//@ check-pass
|
||||
// ICE: #10972
|
||||
// asked to assemble constituent types of unexpected type: Binder(Foo, [])
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
type Foo = impl Debug;
|
||||
const FOO2: Foo = 22_u32;
|
||||
|
||||
pub fn main() {}
|
|
@ -11,7 +11,6 @@ LL | impl PartialOrd for DeriveOrd {
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: `-D clippy::derive-ord-xor-partial-ord` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::derive_ord_xor_partial_ord)]`
|
||||
= note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: you are deriving `Ord` but have implemented `PartialOrd` explicitly
|
||||
--> tests/ui/derive_ord_xor_partial_ord.rs:33:10
|
||||
|
@ -24,7 +23,6 @@ note: `PartialOrd` implemented here
|
|||
|
|
||||
LL | impl PartialOrd<DeriveOrdWithExplicitTypeVariable> for DeriveOrdWithExplicitTypeVariable {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: you are implementing `Ord` explicitly but have derived `PartialOrd`
|
||||
--> tests/ui/derive_ord_xor_partial_ord.rs:47:1
|
||||
|
@ -42,7 +40,6 @@ note: `PartialOrd` implemented here
|
|||
|
|
||||
LL | #[derive(PartialOrd, PartialEq, Eq)]
|
||||
| ^^^^^^^^^^
|
||||
= note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: you are implementing `Ord` explicitly but have derived `PartialOrd`
|
||||
--> tests/ui/derive_ord_xor_partial_ord.rs:69:5
|
||||
|
@ -60,7 +57,6 @@ note: `PartialOrd` implemented here
|
|||
|
|
||||
LL | #[derive(PartialOrd, PartialEq, Eq)]
|
||||
| ^^^^^^^^^^
|
||||
= note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ note: `PartialEq` implemented here
|
|||
LL | impl PartialEq for Bar {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: `#[deny(clippy::derived_hash_with_manual_eq)]` on by default
|
||||
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: you are deriving `Hash` but have implemented `PartialEq` explicitly
|
||||
--> tests/ui/derived_hash_with_manual_eq.rs:23:10
|
||||
|
@ -23,7 +22,6 @@ note: `PartialEq` implemented here
|
|||
|
|
||||
LL | impl PartialEq<Baz> for Baz {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -36,8 +36,6 @@ error: sub-expression diverges
|
|||
|
|
||||
LL | _ => true || panic!("boo"),
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: sub-expression diverges
|
||||
--> tests/ui/diverging_sub_expression.rs:52:29
|
||||
|
|
|
@ -38,7 +38,6 @@ note: potential failure(s)
|
|||
|
|
||||
LL | panic!();
|
||||
| ^^^^^^^^
|
||||
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: consider implementing `TryFrom` instead
|
||||
--> tests/ui/fallible_impl_from.rs:40:1
|
||||
|
@ -64,7 +63,6 @@ LL | } else if s.parse::<u32>().unwrap() != 42 {
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | panic!("{:?}", s);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: consider implementing `TryFrom` instead
|
||||
--> tests/ui/fallible_impl_from.rs:60:1
|
||||
|
@ -85,7 +83,6 @@ LL | if s.parse::<u32>().ok().unwrap() != 42 {
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | panic!("{:?}", s);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ LL | #[derive(Hash)]
|
|||
= note: ... as (`hash("abc") != hash("abc".as_bytes())`
|
||||
= help: consider either removing one of the `Borrow` implementations (`Borrow<str>` or `Borrow<[u8]>`) ...
|
||||
= help: ... or not implementing `Hash` for this type
|
||||
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: the semantics of `Borrow<T>` around `Hash` can't be satisfied when both `Borrow<str>` and `Borrow<[u8]>` are implemented
|
||||
--> tests/ui/impl_hash_with_borrow_str_and_bytes.rs:117:6
|
||||
|
|
|
@ -192,6 +192,7 @@ impl Atpit for () {
|
|||
|
||||
type Tait = impl DerefMut;
|
||||
//~^ implied_bounds_in_impls
|
||||
#[define_opaque(Tait)]
|
||||
fn define() -> Tait {
|
||||
&mut [] as &mut [()]
|
||||
}
|
||||
|
|
|
@ -192,6 +192,7 @@ impl Atpit for () {
|
|||
|
||||
type Tait = impl Deref + DerefMut;
|
||||
//~^ implied_bounds_in_impls
|
||||
#[define_opaque(Tait)]
|
||||
fn define() -> Tait {
|
||||
&mut [] as &mut [()]
|
||||
}
|
||||
|
|
|
@ -6,15 +6,12 @@ LL | byte_view(panic!());
|
|||
|
|
||||
= note: `-D clippy::diverging-sub-expression` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::diverging_sub_expression)]`
|
||||
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: sub-expression diverges
|
||||
--> tests/ui/issue-7447.rs:29:19
|
||||
|
|
||||
LL | group_entries(panic!());
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -207,6 +207,7 @@ mod msrv {
|
|||
mod with_ty_alias {
|
||||
type Foo = impl std::fmt::Debug;
|
||||
|
||||
#[define_opaque(Foo)]
|
||||
fn foo(_: Foo) {
|
||||
let _: Foo = 1;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ mod issue10041 {
|
|||
struct Bomb2;
|
||||
|
||||
impl Bomb2 {
|
||||
#[define_opaque(X)]
|
||||
pub fn new() -> X {
|
||||
//~^ ERROR: overflow evaluating the requirement
|
||||
0i32
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0275]: overflow evaluating the requirement `<i32 as std::ops::Add>::Output == issue10041::X`
|
||||
--> tests/ui/new_ret_no_self_overflow.rs:20:25
|
||||
--> tests/ui/new_ret_no_self_overflow.rs:21:25
|
||||
|
|
||||
LL | pub fn new() -> X {
|
||||
| ^
|
||||
|
|
|
@ -23,7 +23,6 @@ note: existing `clone` defined here
|
|||
|
|
||||
LL | #[derive(Clone)]
|
||||
| ^^^^^
|
||||
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: method's name is the same as an existing method in a trait
|
||||
--> tests/ui/same_name_method.rs:46:13
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue