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 clippy_utils::diagnostics::span_lint_and_note;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
AssocItemKind, FieldDef, HirId, ImplItemRef, IsAuto, Item, ItemKind, Mod, QPath, TraitItemRef, TyKind, UseKind,
|
AssocItemKind, FieldDef, HirId, ImplItemRef, IsAuto, Item, ItemKind, Mod, QPath, TraitItemRef, TyKind, Variant,
|
||||||
Variant, VariantData,
|
VariantData,
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
use rustc_session::impl_lint_pass;
|
use rustc_session::impl_lint_pass;
|
||||||
|
@ -202,11 +202,7 @@ impl ArbitrarySourceItemOrdering {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produces a linting warning for incorrectly ordered item members.
|
/// Produces a linting warning for incorrectly ordered item members.
|
||||||
fn lint_member_name<T: LintContext>(
|
fn lint_member_name<T: LintContext>(cx: &T, ident: &rustc_span::Ident, before_ident: &rustc_span::Ident) {
|
||||||
cx: &T,
|
|
||||||
ident: &rustc_span::symbol::Ident,
|
|
||||||
before_ident: &rustc_span::symbol::Ident,
|
|
||||||
) {
|
|
||||||
span_lint_and_note(
|
span_lint_and_note(
|
||||||
cx,
|
cx,
|
||||||
ARBITRARY_SOURCE_ITEM_ORDERING,
|
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) {
|
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() {
|
let span = if let Some(ident) = item.kind.ident() {
|
||||||
&item.span
|
ident.span
|
||||||
} else {
|
} else {
|
||||||
&item.ident.span
|
item.span
|
||||||
};
|
};
|
||||||
|
|
||||||
let (before_span, note) = if before_item.ident.as_str().is_empty() {
|
let (before_span, note) = if let Some(ident) = before_item.kind.ident() {
|
||||||
(
|
(ident.span, format!("should be placed before `{}`", ident.as_str(),))
|
||||||
&before_item.span,
|
|
||||||
"should be placed before the following item".to_owned(),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
&before_item.ident.span,
|
before_item.span,
|
||||||
format!("should be placed before `{}`", before_item.ident.as_str(),),
|
"should be placed before the following item".to_owned(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -241,7 +234,7 @@ impl ArbitrarySourceItemOrdering {
|
||||||
return;
|
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.
|
/// Produces a linting warning for incorrectly ordered trait items.
|
||||||
|
@ -263,7 +256,7 @@ impl ArbitrarySourceItemOrdering {
|
||||||
impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
|
impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||||
match &item.kind {
|
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;
|
let mut cur_v: Option<&Variant<'_>> = None;
|
||||||
for variant in enum_def.variants {
|
for variant in enum_def.variants {
|
||||||
if variant.span.in_external_macro(cx.sess().source_map()) {
|
if variant.span.in_external_macro(cx.sess().source_map()) {
|
||||||
|
@ -278,7 +271,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
|
||||||
cur_v = Some(variant);
|
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;
|
let mut cur_f: Option<&FieldDef<'_>> = None;
|
||||||
for field in *fields {
|
for field in *fields {
|
||||||
if field.span.in_external_macro(cx.sess().source_map()) {
|
if field.span.in_external_macro(cx.sess().source_map()) {
|
||||||
|
@ -293,7 +286,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
|
||||||
cur_f = Some(field);
|
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 =>
|
if self.enable_ordering_for_trait && *is_auto == IsAuto::No =>
|
||||||
{
|
{
|
||||||
let mut cur_t: Option<&TraitItemRef> = None;
|
let mut cur_t: Option<&TraitItemRef> = None;
|
||||||
|
@ -370,50 +363,24 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following exceptions (skipping with `continue;`) may not be
|
let ident = if let Some(ident) = item.kind.ident() {
|
||||||
// complete, edge cases have not been explored further than what
|
ident
|
||||||
// appears in the existing code base.
|
} else if let ItemKind::Impl(_) = item.kind
|
||||||
if item.ident.name == rustc_span::symbol::kw::Empty {
|
&& !get_item_name(item).is_empty()
|
||||||
if let ItemKind::Impl(_) = item.kind {
|
{
|
||||||
// Sorting trait impls for unnamed types makes no sense.
|
rustc_span::Ident::empty() // FIXME: a bit strange, is there a better way to do it?
|
||||||
if get_item_name(item).is_empty() {
|
} else {
|
||||||
continue;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if item.ident.name.as_str().starts_with('_') {
|
if ident.name.as_str().starts_with('_') {
|
||||||
// Filters out unnamed macro-like impls for various derives,
|
// Filters out unnamed macro-like impls for various derives,
|
||||||
// e.g. serde::Serialize or num_derive::FromPrimitive.
|
// e.g. serde::Serialize or num_derive::FromPrimitive.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if item.ident.name == rustc_span::sym::std && item.span.is_dummy() {
|
if ident.name == rustc_span::sym::std && item.span.is_dummy() {
|
||||||
if let ItemKind::ExternCrate(None) = item.kind {
|
if let ItemKind::ExternCrate(None, _) = item.kind {
|
||||||
// Filters the auto-included Rust standard library.
|
// Filters the auto-included Rust standard library.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -559,6 +526,14 @@ fn get_item_name(item: &Item<'_>) -> String {
|
||||||
String::new()
|
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_config::Conf;
|
||||||
use clippy_utils::msrvs::{self, Msrv, MsrvStack};
|
use clippy_utils::msrvs::{self, Msrv, MsrvStack};
|
||||||
use rustc_ast::{self as ast, Attribute, MetaItemInner, MetaItemKind};
|
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_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
|
||||||
use rustc_session::impl_lint_pass;
|
use rustc_session::impl_lint_pass;
|
||||||
use rustc_span::sym;
|
use rustc_span::sym;
|
||||||
|
@ -465,22 +465,24 @@ impl Attributes {
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for Attributes {
|
impl<'tcx> LateLintPass<'tcx> for Attributes {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
let attrs = cx.tcx.hir_attrs(item.hir_id());
|
||||||
if is_relevant_item(cx, item) {
|
if let ItemKind::Fn { ident, .. } = item.kind
|
||||||
inline_always::check(cx, item.span, item.ident.name, attrs);
|
&& is_relevant_item(cx, item)
|
||||||
|
{
|
||||||
|
inline_always::check(cx, item.span, ident.name, attrs);
|
||||||
}
|
}
|
||||||
repr_attributes::check(cx, item.span, attrs, self.msrv);
|
repr_attributes::check(cx, item.span, attrs, self.msrv);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
|
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
|
||||||
if is_relevant_impl(cx, item) {
|
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<'_>) {
|
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
|
||||||
if is_relevant_trait(cx, item) {
|
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 {
|
if let ItemKind::Fn { body: eid, .. } = item.kind {
|
||||||
is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir_body(eid).value)
|
is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir_body(eid).value)
|
||||||
} else {
|
} 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 {
|
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))
|
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 ImplItemKind::Fn(_, b) = &impl_item.kind
|
||||||
&& let Body { value: func_expr, .. } = cx.tcx.hir_body(*b)
|
&& 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 &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())
|
&& !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() {
|
if adt_def.is_struct() {
|
||||||
check_struct(cx, item, self_ty, func_expr, adt_def, args, cx.tcx.typeck_body(*b));
|
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
|
.tcx
|
||||||
.inherent_impls(def.did())
|
.inherent_impls(def.did())
|
||||||
.iter()
|
.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))
|
.any(|imp| has_unsafe(cx, imp))
|
||||||
{
|
{
|
||||||
span_lint_hir_and_then(
|
span_lint_hir_and_then(
|
||||||
|
|
|
@ -99,7 +99,7 @@ impl_lint_pass!(DisallowedTypes => [DISALLOWED_TYPES]);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
|
impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
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 {
|
for res in &path.res {
|
||||||
self.check_res_emit(cx, res, item.span);
|
self.check_res_emit(cx, res, item.span);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ pub fn check(
|
||||||
&& cx
|
&& cx
|
||||||
.tcx
|
.tcx
|
||||||
.hir_parent_iter(owner_id.into())
|
.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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
|
||||||
if cx.tcx.data_layout.pointer_size.bits() != 64 {
|
if cx.tcx.data_layout.pointer_size.bits() != 64 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let ItemKind::Enum(def, _) = &item.kind {
|
if let ItemKind::Enum(_, def, _) = &item.kind {
|
||||||
for var in def.variants {
|
for var in def.variants {
|
||||||
if let Some(anon_const) = &var.disr_expr {
|
if let Some(anon_const) = &var.disr_expr {
|
||||||
let def_id = cx.tcx.hir_body_owner_def_id(anon_const.body);
|
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 {
|
impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||||
match item.kind {
|
match item.kind {
|
||||||
ItemKind::TyAlias(..)
|
ItemKind::TyAlias(ident, ..)
|
||||||
if item.ident.name == sym::Error
|
if ident.name == sym::Error
|
||||||
&& is_visible_outside_module(cx, item.owner_id.def_id)
|
&& is_visible_outside_module(cx, item.owner_id.def_id)
|
||||||
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
|
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
|
||||||
&& let Some(error_def_id) = cx.tcx.get_diagnostic_item(sym::Error)
|
&& let Some(error_def_id) = cx.tcx.get_diagnostic_item(sym::Error)
|
||||||
|
@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
|
||||||
span_lint(
|
span_lint(
|
||||||
cx,
|
cx,
|
||||||
ERROR_IMPL_ERROR,
|
ERROR_IMPL_ERROR,
|
||||||
item.ident.span,
|
ident.span,
|
||||||
"exported type alias named `Error` that implements `Error`",
|
"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
|
// 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 {
|
for trait_item in items {
|
||||||
if trait_item.id.owner_id.def_id == fn_def_id {
|
if trait_item.id.owner_id.def_id == fn_def_id {
|
||||||
// be sure we have `self` parameter in this function
|
// 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) {
|
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {
|
||||||
if cmt.place.projections.is_empty() {
|
if cmt.place.projections.is_empty() {
|
||||||
if let PlaceBase::Local(lid) = cmt.place.base {
|
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) {
|
fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId) {
|
||||||
if cmt.place.projections.is_empty() {
|
if cmt.place.projections.is_empty() && is_argument(self.cx.tcx, cmt.hir_id) {
|
||||||
let map = &self.cx.tcx.hir();
|
// Skip closure arguments
|
||||||
if is_argument(self.cx.tcx, cmt.hir_id) {
|
let parent_id = self.cx.tcx.parent_hir_id(cmt.hir_id);
|
||||||
// Skip closure arguments
|
if let Node::Expr(..) = self.cx.tcx.parent_hir_node(parent_id) {
|
||||||
let parent_id = self.cx.tcx.parent_hir_id(cmt.hir_id);
|
return;
|
||||||
if let Node::Expr(..) = self.cx.tcx.parent_hir_node(parent_id) {
|
}
|
||||||
|
|
||||||
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// skip if there is a `self` parameter binding to a type
|
if is_non_trait_box(cmt.place.ty()) && !self.is_large_box(cmt.place.ty()) {
|
||||||
// that contains `Self` (i.e.: `self: Box<Self>`), see #4804
|
self.set.insert(cmt.hir_id);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,7 @@ fn check_fn_decl(cx: &LateContext<'_>, decl: &FnDecl<'_>, sp: Span, max: u64) {
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
|
impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
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
|
&& variant_data.fields().len() as u64 > self.max_struct_bools
|
||||||
&& has_n_bools(
|
&& has_n_bools(
|
||||||
variant_data.fields().iter().map(|field| field.ty),
|
variant_data.fields().iter().map(|field| field.ty),
|
||||||
|
|
|
@ -76,7 +76,7 @@ impl LateLintPass<'_> for ExhaustiveItems {
|
||||||
"exported enums should not be exhaustive",
|
"exported enums should not be exhaustive",
|
||||||
[].as_slice(),
|
[].as_slice(),
|
||||||
),
|
),
|
||||||
ItemKind::Struct(v, ..) => (
|
ItemKind::Struct(_, v, ..) => (
|
||||||
EXHAUSTIVE_STRUCTS,
|
EXHAUSTIVE_STRUCTS,
|
||||||
"exported structs should not be exhaustive",
|
"exported structs should not be exhaustive",
|
||||||
v.fields(),
|
v.fields(),
|
||||||
|
@ -84,7 +84,7 @@ impl LateLintPass<'_> for ExhaustiveItems {
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
if cx.effective_visibilities.is_exported(item.owner_id.def_id)
|
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))
|
&& !attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
|
||||||
&& fields.iter().all(|f| cx.tcx.visibility(f.def_id).is_public())
|
&& 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)
|
// 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
|
// Since the argument to fmt is itself a reference: &self
|
||||||
let reference = peel_ref_operators(self.cx, arg);
|
let reference = peel_ref_operators(self.cx, arg);
|
||||||
let map = self.cx.tcx.hir();
|
|
||||||
// Is the reference self?
|
// 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;
|
let FormatTraitNames { name, .. } = self.format_trait_impl;
|
||||||
span_lint(
|
span_lint(
|
||||||
self.cx,
|
self.cx,
|
||||||
|
|
|
@ -43,8 +43,7 @@ impl<'tcx> LateLintPass<'tcx> for FourForwardSlashes {
|
||||||
let sm = cx.sess().source_map();
|
let sm = cx.sess().source_map();
|
||||||
let mut span = cx
|
let mut span = cx
|
||||||
.tcx
|
.tcx
|
||||||
.hir()
|
.hir_attrs(item.hir_id())
|
||||||
.attrs(item.hir_id())
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|i| i.is_doc_comment())
|
.filter(|i| i.is_doc_comment())
|
||||||
.fold(item.span.shrink_to_lo(), |span, attr| span.to(attr.span()));
|
.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};
|
use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT};
|
||||||
|
|
||||||
pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
|
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);
|
let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
|
||||||
if let hir::ItemKind::Fn {
|
if let hir::ItemKind::Fn {
|
||||||
ref sig,
|
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 {
|
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 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 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);
|
let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
|
||||||
if let Some(attr) = attr {
|
if let Some(attr) = attr {
|
||||||
check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig);
|
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 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 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);
|
let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
|
||||||
if let Some(attr) = attr {
|
if let Some(attr) = attr {
|
||||||
check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig);
|
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()
|
.did()
|
||||||
.as_local()
|
.as_local()
|
||||||
&& let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(local_def_id)
|
&& 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);
|
let variants_size = AdtVariantInfo::new(cx, *adt, subst);
|
||||||
if let Some((first_variant, variants)) = variants_size.split_first()
|
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 {
|
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())
|
field.span.with_lo(attr.span().lo())
|
||||||
} else {
|
} else {
|
||||||
field.span
|
field.span
|
||||||
|
|
|
@ -32,12 +32,7 @@ declare_lint_pass!(InlineFnWithoutBody => [INLINE_FN_WITHOUT_BODY]);
|
||||||
impl<'tcx> LateLintPass<'tcx> for InlineFnWithoutBody {
|
impl<'tcx> LateLintPass<'tcx> for InlineFnWithoutBody {
|
||||||
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
|
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
|
||||||
if let TraitItemKind::Fn(_, TraitFn::Required(_)) = item.kind
|
if let TraitItemKind::Fn(_, TraitFn::Required(_)) = item.kind
|
||||||
&& let Some(attr) = cx
|
&& let Some(attr) = cx.tcx.hir_attrs(item.hir_id()).iter().find(|a| a.has_name(sym::inline))
|
||||||
.tcx
|
|
||||||
.hir()
|
|
||||||
.attrs(item.hir_id())
|
|
||||||
.iter()
|
|
||||||
.find(|a| a.has_name(sym::inline))
|
|
||||||
{
|
{
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
cx,
|
cx,
|
||||||
|
|
|
@ -206,7 +206,10 @@ impl ItemNameRepetitions {
|
||||||
return;
|
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 {
|
for var in def.variants {
|
||||||
check_enum_start(cx, item_name, var);
|
check_enum_start(cx, item_name, var);
|
||||||
check_enum_end(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<'_>]) {
|
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.
|
// 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
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,14 +352,15 @@ impl ItemNameRepetitions {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_struct_name_repetition(&self, cx: &LateContext<'_>, item: &Item<'_>, fields: &[FieldDef<'_>]) {
|
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();
|
let item_name_words: Vec<&str> = snake_name.split('_').collect();
|
||||||
for field in fields {
|
for field in fields {
|
||||||
if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(field.def_id) {
|
if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(field.def_id) {
|
||||||
continue;
|
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)
|
// consider linting only if the field identifier has the same SyntaxContext as the item(struct)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -426,19 +433,23 @@ fn check_enum_end(cx: &LateContext<'_>, item_name: &str, variant: &Variant<'_>)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass<'_> for ItemNameRepetitions {
|
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();
|
let last = self.modules.pop();
|
||||||
assert!(last.is_some());
|
assert!(last.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
|
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);
|
let item_camel = to_camel_case(item_name);
|
||||||
if !item.span.from_expansion() && is_present_in_source(cx, item.span) {
|
if !item.span.from_expansion() && is_present_in_source(cx, item.span) {
|
||||||
if let [.., (mod_name, mod_camel, mod_owner_id)] = &*self.modules {
|
if let [.., (mod_name, mod_camel, mod_owner_id)] = &*self.modules {
|
||||||
// constants don't have surrounding modules
|
// constants don't have surrounding modules
|
||||||
if !mod_camel.is_empty() {
|
if !mod_camel.is_empty() {
|
||||||
if mod_name == &item.ident.name
|
if mod_name == &ident.name
|
||||||
&& let ItemKind::Mod(..) = item.kind
|
&& let ItemKind::Mod(..) = item.kind
|
||||||
&& (!self.allow_private_module_inception || cx.tcx.visibility(mod_owner_id.def_id).is_public())
|
&& (!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(
|
Some(c) if is_word_beginning(c) => span_lint(
|
||||||
cx,
|
cx,
|
||||||
MODULE_NAME_REPETITIONS,
|
MODULE_NAME_REPETITIONS,
|
||||||
item.ident.span,
|
ident.span,
|
||||||
"item name starts with its containing module's name",
|
"item name starts with its containing module's name",
|
||||||
),
|
),
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -479,7 +490,7 @@ impl LateLintPass<'_> for ItemNameRepetitions {
|
||||||
span_lint(
|
span_lint(
|
||||||
cx,
|
cx,
|
||||||
MODULE_NAME_REPETITIONS,
|
MODULE_NAME_REPETITIONS,
|
||||||
item.ident.span,
|
ident.span,
|
||||||
"item name ends with its containing module's name",
|
"item name ends with its containing module's name",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -490,16 +501,15 @@ impl LateLintPass<'_> for ItemNameRepetitions {
|
||||||
|
|
||||||
if span_is_local(item.span) {
|
if span_is_local(item.span) {
|
||||||
match item.kind {
|
match item.kind {
|
||||||
ItemKind::Enum(def, _) => {
|
ItemKind::Enum(_, def, _) => {
|
||||||
self.check_variants(cx, item, &def);
|
self.check_variants(cx, item, &def);
|
||||||
},
|
},
|
||||||
ItemKind::Struct(VariantData::Struct { fields, .. }, _) => {
|
ItemKind::Struct(_, VariantData::Struct { fields, .. }, _) => {
|
||||||
self.check_fields(cx, item, fields);
|
self.check_fields(cx, item, fields);
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.modules.push((ident.name, item_camel, item.owner_id));
|
||||||
self.modules.push((item.ident.name, item_camel, item.owner_id));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ declare_clippy_lint! {
|
||||||
declare_lint_pass!(ItemsAfterTestModule => [ITEMS_AFTER_TEST_MODULE]);
|
declare_lint_pass!(ItemsAfterTestModule => [ITEMS_AFTER_TEST_MODULE]);
|
||||||
|
|
||||||
fn cfg_test_module<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool {
|
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()
|
&& item.span.hi() == test_mod.spans.inner_span.hi()
|
||||||
&& is_cfg_test(cx.tcx, item.hir_id())
|
&& is_cfg_test(cx.tcx, item.hir_id())
|
||||||
&& !item.span.from_expansion()
|
&& !item.span.from_expansion()
|
||||||
|
@ -67,14 +67,20 @@ impl LateLintPass<'_> for ItemsAfterTestModule {
|
||||||
let after: Vec<_> = items
|
let after: Vec<_> = items
|
||||||
.filter(|item| {
|
.filter(|item| {
|
||||||
// Ignore the generated test main function
|
// Ignore the generated test main function
|
||||||
!(item.ident.name == sym::main
|
if let ItemKind::Fn { ident, .. } = item.kind
|
||||||
&& item.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::TestHarness))
|
&& ident.name == sym::main
|
||||||
|
&& item.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::TestHarness)
|
||||||
|
{
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if let Some(last) = after.last()
|
if let Some(last) = after.last()
|
||||||
&& after.iter().all(|&item| {
|
&& 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()))
|
&& !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 {
|
impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
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.
|
// 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
|
// 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.
|
// 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())
|
&& 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)
|
&& 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(
|
let sugg_span = Span::new(
|
||||||
hi_pos - BytePos::from_usize("const".len()),
|
hi_pos - BytePos::from_usize("const".len()),
|
||||||
hi_pos,
|
hi_pos,
|
||||||
|
|
|
@ -73,7 +73,7 @@ impl_lint_pass!(LargeEnumVariant => [LARGE_ENUM_VARIANT]);
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
|
impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &Item<'tcx>) {
|
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 = cx.tcx.type_of(item.owner_id).instantiate_identity()
|
||||||
&& let ty::Adt(adt, subst) = ty.kind()
|
&& let ty::Adt(adt, subst) = ty.kind()
|
||||||
&& adt.variants().len() > 1
|
&& adt.variants().len() > 1
|
||||||
|
@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
|
||||||
let mut applicability = Applicability::MaybeIncorrect;
|
let mut applicability = Applicability::MaybeIncorrect;
|
||||||
if is_copy(cx, ty) || maybe_copy(cx, ty) {
|
if is_copy(cx, ty) || maybe_copy(cx, ty) {
|
||||||
diag.span_note(
|
diag.span_note(
|
||||||
item.ident.span,
|
ident.span,
|
||||||
"boxing a variant would require the type no longer be `Copy`",
|
"boxing a variant would require the type no longer be `Copy`",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||||
// Integer modules are "TBD" deprecated, and the contents are too,
|
// Integer modules are "TBD" deprecated, and the contents are too,
|
||||||
// so lint on the `use` statement directly.
|
// 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())
|
&& !item.span.in_external_macro(cx.sess().source_map())
|
||||||
&& let Some(def_id) = path.res[0].opt_def_id()
|
&& let Some(def_id) = path.res[0].opt_def_id()
|
||||||
&& self.msrv.meets(cx, msrvs::NUMERIC_ASSOCIATED_CONSTANTS)
|
&& self.msrv.meets(cx, msrvs::NUMERIC_ASSOCIATED_CONSTANTS)
|
||||||
|
@ -72,7 +72,9 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
|
||||||
"importing a legacy numeric constant"
|
"importing a legacy numeric constant"
|
||||||
},
|
},
|
||||||
|diag| {
|
|diag| {
|
||||||
if item.ident.name == kw::Underscore {
|
if let UseKind::Single(ident) = kind
|
||||||
|
&& ident.name == kw::Underscore
|
||||||
|
{
|
||||||
diag.help("remove this import");
|
diag.help("remove this import");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ use rustc_middle::ty::{self, AssocKind, FnSig, Ty};
|
||||||
use rustc_session::declare_lint_pass;
|
use rustc_session::declare_lint_pass;
|
||||||
use rustc_span::source_map::Spanned;
|
use rustc_span::source_map::Spanned;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Ident, Span, Symbol};
|
||||||
use rustc_trait_selection::traits::supertrait_def_ids;
|
use rustc_trait_selection::traits::supertrait_def_ids;
|
||||||
|
|
||||||
declare_clippy_lint! {
|
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 {
|
impl<'tcx> LateLintPass<'tcx> for LenZero {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
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()
|
&& !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) {
|
let (name, kind) = match cx.tcx.hir_node(ty_hir_id) {
|
||||||
Node::ForeignItem(x) => (x.ident.name, "extern type"),
|
Node::ForeignItem(x) => (x.ident.name, "extern type"),
|
||||||
Node::Item(x) => match x.kind {
|
Node::Item(x) => match x.kind {
|
||||||
ItemKind::Struct(..) => (x.ident.name, "struct"),
|
ItemKind::Struct(ident, ..) => (ident.name, "struct"),
|
||||||
ItemKind::Enum(..) => (x.ident.name, "enum"),
|
ItemKind::Enum(ident, ..) => (ident.name, "enum"),
|
||||||
ItemKind::Union(..) => (x.ident.name, "union"),
|
ItemKind::Union(ident, ..) => (ident.name, "union"),
|
||||||
_ => (x.ident.name, "type"),
|
_ => (x.kind.ident().unwrap().name, "type"),
|
||||||
},
|
},
|
||||||
_ => return,
|
_ => 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 {
|
fn is_named_self(cx: &LateContext<'_>, item: &TraitItemRef, name: Symbol) -> bool {
|
||||||
item.ident.name == name
|
item.ident.name == name
|
||||||
&& if let AssocItemKind::Fn { has_self } = item.kind {
|
&& 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,
|
visited_trait.span,
|
||||||
format!(
|
format!(
|
||||||
"trait `{}` has a `len` method but no (possibly inherited) `is_empty` method",
|
"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> {
|
impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
|
||||||
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
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) {
|
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) {
|
||||||
if bk == ty::BorrowKind::Mutable {
|
if bk == ty::BorrowKind::Mutable {
|
||||||
if let PlaceBase::Local(id) = cmt.place.base {
|
if let PlaceBase::Local(id) = cmt.place.base {
|
||||||
|
@ -127,7 +129,7 @@ impl BreakAfterExprVisitor {
|
||||||
};
|
};
|
||||||
|
|
||||||
get_enclosing_block(cx, hir_id).is_some_and(|block| {
|
get_enclosing_block(cx, hir_id).is_some_and(|block| {
|
||||||
visitor.visit_block(block);
|
let _ = visitor.visit_block(block);
|
||||||
visitor.break_after_expr
|
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::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::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::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, _) => {
|
ExprKind::MethodCall(_, receiver, es, _) => {
|
||||||
never_loop_expr_all(cx, once(receiver).chain(es.iter()), local_labels, main_loop_id)
|
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
|
if cx.sess().opts.edition >= Edition::Edition2018
|
||||||
&& let hir::ItemKind::Use(path, _kind) = &item.kind
|
&& let hir::ItemKind::Use(path, _kind) = &item.kind
|
||||||
&& let hir_id = item.hir_id()
|
&& 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(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use))
|
||||||
&& let Some(id) = path.res.iter().find_map(|res| match res {
|
&& let Some(id) = path.res.iter().find_map(|res| match res {
|
||||||
Res::Def(DefKind::Mod, id) => Some(id),
|
Res::Def(DefKind::Mod, id) => Some(id),
|
||||||
|
|
|
@ -87,18 +87,18 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
|
||||||
}
|
}
|
||||||
|
|
||||||
match item.kind {
|
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| {
|
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))
|
.then_some((v.def_id, v.span))
|
||||||
});
|
});
|
||||||
if let Ok((id, span)) = iter.exactly_one()
|
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));
|
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 fields = variant_data.fields();
|
||||||
let private_fields = fields
|
let private_fields = fields
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
|
||||||
"this seems like a manual implementation of the non-exhaustive pattern",
|
"this seems like a manual implementation of the non-exhaustive pattern",
|
||||||
|diag| {
|
|diag| {
|
||||||
if let Some(non_exhaustive) =
|
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");
|
diag.span_note(non_exhaustive.span(), "the struct is already non-exhaustive");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -99,7 +99,7 @@ where
|
||||||
});
|
});
|
||||||
if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(l), .. })) = e.kind {
|
if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(l), .. })) = e.kind {
|
||||||
match captures.get(l) {
|
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 => {
|
Some(CaptureKind::Ref(Mutability::Not)) if binding_ref_mutability == Mutability::Mut => {
|
||||||
return None;
|
return None;
|
||||||
},
|
},
|
||||||
|
|
|
@ -42,7 +42,7 @@ pub(super) fn check_match<'tcx>(
|
||||||
cx,
|
cx,
|
||||||
scrutinee,
|
scrutinee,
|
||||||
arms.iter()
|
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,
|
e,
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
|
|
|
@ -75,7 +75,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
|
||||||
HirIdMapEntry::Occupied(entry) => return *entry.get() == b_id,
|
HirIdMapEntry::Occupied(entry) => return *entry.get() == b_id,
|
||||||
}
|
}
|
||||||
// the names technically don't have to match; this makes the lint more conservative
|
// 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)
|
&& cx.typeck_results().expr_ty(a) == cx.typeck_results().expr_ty(b)
|
||||||
&& pat_contains_local(lhs.pat, a_id)
|
&& pat_contains_local(lhs.pat, a_id)
|
||||||
&& pat_contains_local(rhs.pat, b_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 {
|
fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool {
|
||||||
cx.tcx
|
cx.tcx
|
||||||
.hir_parent_id_iter(id)
|
.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
|
/// 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 borrow(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId, _: BorrowKind) {}
|
||||||
|
|
||||||
fn mutate(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
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 name = impl_item.ident.name.as_str();
|
||||||
let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
|
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 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(_), .. }));
|
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,
|
// 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()`
|
// 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)
|
// 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) {
|
if let Some(parent) = get_parent_expr(cx, expr) {
|
||||||
let data = if let ExprKind::MethodCall(segment, recv, args, span) = parent.kind {
|
let data = if let ExprKind::MethodCall(segment, recv, args, span) = parent.kind {
|
||||||
if args.is_empty()
|
if args.is_empty()
|
||||||
|
|
|
@ -182,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
|
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");
|
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<'_>) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) {
|
||||||
match it.kind {
|
match it.kind {
|
||||||
hir::ItemKind::Fn { .. } => {
|
hir::ItemKind::Fn { ident, .. } => {
|
||||||
// ignore main()
|
// 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;
|
let at_root = cx.tcx.local_parent(it.owner_id.def_id) == CRATE_DEF_ID;
|
||||||
if at_root {
|
if at_root {
|
||||||
note_prev_span_then_ret!(self.prev_span, it.span);
|
note_prev_span_then_ret!(self.prev_span, it.span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hir::ItemKind::Const(..) => {
|
hir::ItemKind::Const(ident, ..) => {
|
||||||
if it.ident.name == kw::Underscore {
|
if ident.name == kw::Underscore {
|
||||||
note_prev_span_then_ret!(self.prev_span, it.span);
|
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 (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) {
|
if !is_from_proc_macro(cx, it) {
|
||||||
self.check_missing_docs_attrs(cx, it.owner_id.def_id, attrs, it.span, article, desc);
|
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<'_>) {
|
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 (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) {
|
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);
|
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 (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) {
|
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);
|
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<'_>) {
|
fn check_field_def(&mut self, cx: &LateContext<'tcx>, sf: &'tcx hir::FieldDef<'_>) {
|
||||||
if !sf.is_positional() {
|
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) {
|
if !is_from_proc_macro(cx, sf) {
|
||||||
self.check_missing_docs_attrs(cx, sf.def_id, attrs, sf.span, "a", "struct field");
|
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<'_>) {
|
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) {
|
if !is_from_proc_macro(cx, v) {
|
||||||
self.check_missing_docs_attrs(cx, v.def_id, attrs, v.span, "a", "variant");
|
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 {
|
impl LateLintPass<'_> for ImportRename {
|
||||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
|
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 {
|
for &res in &path.res {
|
||||||
if let Res::Def(_, id) = res
|
if let Res::Def(_, id) = res
|
||||||
&& let Some(name) = self.renames.get(&id)
|
&& let Some(name) = self.renames.get(&id)
|
||||||
|
|
|
@ -226,7 +226,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug {
|
||||||
&& should_lint(cx, typeck_results, block)
|
&& should_lint(cx, typeck_results, block)
|
||||||
{
|
{
|
||||||
// we intentionally only lint structs, see lint description
|
// 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);
|
check_struct(cx, typeck_results, block, self_ty, item, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,10 +98,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
|
||||||
match it.kind {
|
match it.kind {
|
||||||
hir::ItemKind::Fn { .. } => {
|
hir::ItemKind::Fn { .. } => {
|
||||||
let desc = "a function";
|
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);
|
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
|
// note: we need to check if the trait is exported so we can't use
|
||||||
// `LateLintPass::check_trait_item` here.
|
// `LateLintPass::check_trait_item` here.
|
||||||
for tit in trait_items {
|
for tit in trait_items {
|
||||||
|
@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
|
||||||
// an impl is not provided
|
// an impl is not provided
|
||||||
let desc = "a default trait method";
|
let desc = "a default trait method";
|
||||||
let item = cx.tcx.hir_trait_item(tit.id);
|
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);
|
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);
|
check_missing_inline_attrs(cx, attrs, impl_item.span, desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -334,7 +334,7 @@ impl<'tcx> Visitor<'tcx> for ReadVisitor<'_, 'tcx> {
|
||||||
self.cx,
|
self.cx,
|
||||||
MIXED_READ_WRITE_IN_EXPRESSION,
|
MIXED_READ_WRITE_IN_EXPRESSION,
|
||||||
expr.span,
|
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| {
|
||||||
diag.span_note(
|
diag.span_note(
|
||||||
self.write_expr.span,
|
self.write_expr.span,
|
||||||
|
|
|
@ -65,7 +65,7 @@ impl LateLintPass<'_> for NeedlessIf {
|
||||||
stmt.span,
|
stmt.span,
|
||||||
"this `if` branch is empty",
|
"this `if` branch is empty",
|
||||||
"you can remove it",
|
"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
|
// `{ foo }` or `{ foo } && bar` placed into a statement position would be
|
||||||
// interpreted as a block statement, force it to be an expression
|
// interpreted as a block statement, force it to be an expression
|
||||||
if cond_snippet.starts_with('{') {
|
if cond_snippet.starts_with('{') {
|
||||||
|
|
|
@ -259,7 +259,7 @@ fn check<'tcx>(
|
||||||
binding_id: HirId,
|
binding_id: HirId,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
let usage = first_usage(cx, binding_id, local_stmt.hir_id, block)?;
|
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)?;
|
let let_snippet = local_snippet_without_semicolon(cx, local)?;
|
||||||
|
|
||||||
match usage.expr.kind {
|
match usage.expr.kind {
|
||||||
|
|
|
@ -147,7 +147,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
|
||||||
// We don't check unsafe functions.
|
// We don't check unsafe functions.
|
||||||
return;
|
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) {
|
if header.abi != ExternAbi::Rust || requires_exact_signature(attrs) {
|
||||||
return;
|
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)]
|
#[allow(clippy::if_same_then_else)]
|
||||||
fn borrow(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, id: HirId, borrow: ty::BorrowKind) {
|
fn borrow(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, id: HirId, borrow: ty::BorrowKind) {
|
||||||
self.prev_bind = None;
|
self.prev_bind = None;
|
||||||
|
|
|
@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
|
||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
FnKind::ItemFn(.., header) => {
|
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) {
|
if header.abi != ExternAbi::Rust || requires_exact_signature(attrs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -326,6 +326,8 @@ impl<'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt {
|
||||||
self.move_common(cmt);
|
self.move_common(cmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn use_cloned(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId) {}
|
||||||
|
|
||||||
fn borrow(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {}
|
fn borrow(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {}
|
||||||
|
|
||||||
fn mutate(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId) {}
|
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 {
|
impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
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()
|
&& !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 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 {
|
for attr in attrs {
|
||||||
if let Some(ident) = attr.ident()
|
if let Some(ident) = attr.ident()
|
||||||
&& ident.name == rustc_span::sym::no_mangle
|
&& 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<'_>) {
|
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
|
||||||
if let ImplItemKind::Const(_, body_id) = &impl_item.kind {
|
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_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 {
|
match &item.kind {
|
||||||
ItemKind::Impl(Impl {
|
ItemKind::Impl(Impl {
|
||||||
|
|
|
@ -192,7 +192,7 @@ struct LazyInfo {
|
||||||
impl LazyInfo {
|
impl LazyInfo {
|
||||||
fn from_item(state: &NonStdLazyStatic, cx: &LateContext<'_>, item: &Item<'_>) -> Option<Self> {
|
fn from_item(state: &NonStdLazyStatic, cx: &LateContext<'_>, item: &Item<'_>) -> Option<Self> {
|
||||||
// Check if item is a `once_cell:sync::Lazy` static.
|
// 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 Some(path_def_id) = path_def_id(cx, ty)
|
||||||
&& let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
|
&& let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
|
||||||
&& state.once_cell_sync_lazy.contains(&path_def_id)
|
&& 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 consume(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
|
||||||
|
fn use_cloned(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
|
||||||
fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
|
fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
|
||||||
fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: HirId) {}
|
fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: HirId) {}
|
||||||
fn copy(&mut self, _: &PlaceWithHirId<'_>, _: 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 consume(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
|
||||||
|
fn use_cloned(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
|
||||||
fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
|
fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
|
||||||
fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: HirId) {}
|
fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: HirId) {}
|
||||||
fn copy(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
|
fn copy(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
|
||||||
|
|
|
@ -50,7 +50,7 @@ pub(crate) fn check<'tcx>(
|
||||||
// format the suggestion
|
// format the suggestion
|
||||||
let suggestion = format!(
|
let suggestion = format!(
|
||||||
"{}.abs()",
|
"{}.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
|
// spans the lint
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
|
|
|
@ -181,7 +181,7 @@ fn in_impl<'tcx>(
|
||||||
) -> Option<(&'tcx rustc_hir::Ty<'tcx>, &'tcx rustc_hir::Ty<'tcx>)> {
|
) -> Option<(&'tcx rustc_hir::Ty<'tcx>, &'tcx rustc_hir::Ty<'tcx>)> {
|
||||||
if let Some(block) = get_enclosing_block(cx, e.hir_id)
|
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 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 ItemKind::Impl(item) = &item.kind
|
||||||
&& let Some(of_trait) = &item.of_trait
|
&& let Some(of_trait) = &item.of_trait
|
||||||
&& let Some(seg) = of_trait.path.segments.last()
|
&& 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 {
|
fn are_equal(cx: &LateContext<'_>, middle_ty: Ty<'_>, hir_ty: &rustc_hir::Ty<'_>) -> bool {
|
||||||
if let ty::Adt(adt_def, _) = middle_ty.kind()
|
if let ty::Adt(adt_def, _) = middle_ty.kind()
|
||||||
&& let Some(local_did) = adt_def.did().as_local()
|
&& 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 middle_ty_id = item.owner_id.to_def_id()
|
||||||
&& let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind
|
&& let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind
|
||||||
&& let Res::Def(_, hir_ty_id) = path.res
|
&& let Res::Def(_, hir_ty_id) = path.res
|
||||||
|
|
|
@ -185,7 +185,7 @@ fn try_get_option_occurrence<'tcx>(
|
||||||
.then_some(())
|
.then_some(())
|
||||||
.and_then(|()| none_captures.get(local_id))
|
.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)) if as_mut => return None,
|
||||||
Some(CaptureKind::Ref(Mutability::Not)) | 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
|
// Gather all the lifetimes found in the output type which may affect whether
|
||||||
// `TRIVIALLY_COPY_PASS_BY_REF` should be linted.
|
// `TRIVIALLY_COPY_PASS_BY_REF` should be linted.
|
||||||
let mut output_regions = FxHashSet::default();
|
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);
|
output_regions.insert(region);
|
||||||
ControlFlow::Continue(())
|
ControlFlow::Continue(())
|
||||||
});
|
});
|
||||||
|
@ -280,7 +280,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
|
||||||
if header.abi != ExternAbi::Rust {
|
if header.abi != ExternAbi::Rust {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let attrs = cx.tcx.hir().attrs(hir_id);
|
let attrs = cx.tcx.hir_attrs(hir_id);
|
||||||
for a in attrs {
|
for a in attrs {
|
||||||
if let Some(meta_items) = a.meta_item_list() {
|
if let Some(meta_items) = a.meta_item_list() {
|
||||||
if a.has_name(sym::proc_macro_derive)
|
if a.has_name(sym::proc_macro_derive)
|
||||||
|
|
|
@ -58,7 +58,7 @@ impl PubUnderscoreFields {
|
||||||
impl<'tcx> LateLintPass<'tcx> for PubUnderscoreFields {
|
impl<'tcx> LateLintPass<'tcx> for PubUnderscoreFields {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||||
// This lint only pertains to structs.
|
// This lint only pertains to structs.
|
||||||
let ItemKind::Struct(variant_data, _) = &item.kind else {
|
let ItemKind::Struct(_, variant_data, _) = &item.kind else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for PubUnderscoreFields {
|
||||||
// Only pertains to fields that start with an underscore, and are public.
|
// Only pertains to fields that start with an underscore, and are public.
|
||||||
if field.ident.as_str().starts_with('_') && is_visible(field)
|
if field.ident.as_str().starts_with('_') && is_visible(field)
|
||||||
// We ignore fields that have `#[doc(hidden)]`.
|
// 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`.
|
// We ignore fields that are `PhantomData`.
|
||||||
&& !is_path_lang_item(cx, field.ty, LangItem::PhantomData)
|
&& !is_path_lang_item(cx, field.ty, LangItem::PhantomData)
|
||||||
{
|
{
|
||||||
|
|
|
@ -93,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
VecInitKind::WithExprCapacity(hir_id) => {
|
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(
|
span_lint_hir_and_then(
|
||||||
cx,
|
cx,
|
||||||
READ_ZERO_BYTE_VEC,
|
READ_ZERO_BYTE_VEC,
|
||||||
|
|
|
@ -52,7 +52,13 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
|
||||||
&& is_not_macro_export(item)
|
&& is_not_macro_export(item)
|
||||||
&& !item.span.in_external_macro(cx.sess().source_map())
|
&& !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());
|
let descr = cx.tcx.def_kind(item.owner_id).descr(item.owner_id.to_def_id());
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
cx,
|
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.
|
// We only show this warning for public exported methods.
|
||||||
&& cx.effective_visibilities.is_exported(fn_def)
|
&& cx.effective_visibilities.is_exported(fn_def)
|
||||||
// We don't want to emit this lint if the `#[must_use]` attribute is already there.
|
// 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()
|
&& cx.tcx.visibility(fn_def.to_def_id()).is_public()
|
||||||
&& let ret_ty = return_ty(cx, owner_id)
|
&& let ret_ty = return_ty(cx, owner_id)
|
||||||
&& let self_arg = nth_arg(cx, owner_id, 0)
|
&& 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 Some(stmt) = block.stmts.iter().last()
|
||||||
&& let StmtKind::Let(local) = &stmt.kind
|
&& let StmtKind::Let(local) = &stmt.kind
|
||||||
&& local.ty.is_none()
|
&& 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 Some(initexpr) = &local.init
|
||||||
&& let PatKind::Binding(_, local_id, _, _) = local.pat.kind
|
&& let PatKind::Binding(_, local_id, _, _) = local.pat.kind
|
||||||
&& path_to_local_id(retexpr, local_id)
|
&& 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)
|
// This allows the addition of attributes, like `#[allow]` (See: clippy#9361)
|
||||||
// `#[expect(clippy::needless_return)]` needs to be handled separately to
|
// `#[expect(clippy::needless_return)]` needs to be handled separately to
|
||||||
// actually fulfill the expectation (clippy::#12998)
|
// actually fulfill the expectation (clippy::#12998)
|
||||||
match cx.tcx.hir().attrs(expr.hir_id) {
|
match cx.tcx.hir_attrs(expr.hir_id) {
|
||||||
[] => {},
|
[] => {},
|
||||||
[attr] => {
|
[attr] => {
|
||||||
if matches!(Level::from_attr(attr), Some(Level::Expect(_)))
|
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 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 self_ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
|
||||||
let ret_ty = return_ty(cx, impl_item.owner_id);
|
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()
|
if let Some(self_def) = self_ty.ty_adt_def()
|
||||||
&& let Some(self_local_did) = self_def.did().as_local()
|
&& 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 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() == type_name
|
||||||
|| impl_item.ident.name.as_str().replace('_', "") == 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 {
|
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 Some(last_field) = data.fields().last()
|
||||||
&& let field_ty = cx.tcx.normalize_erasing_regions(
|
&& let field_ty = cx.tcx.normalize_erasing_regions(
|
||||||
cx.typing_env(),
|
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
|
// special handling for self trait bounds as these are not considered generics
|
||||||
// ie. trait Foo: Display {}
|
// ie. trait Foo: Display {}
|
||||||
if let Item {
|
if let Item {
|
||||||
kind: ItemKind::Trait(_, _, _, bounds, ..),
|
kind: ItemKind::Trait(_, _, _, _, bounds, ..),
|
||||||
..
|
..
|
||||||
} = item
|
} = item
|
||||||
{
|
{
|
||||||
|
@ -133,7 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
|
||||||
..
|
..
|
||||||
}) = segments.first()
|
}) = segments.first()
|
||||||
&& let Some(Node::Item(Item {
|
&& let Some(Node::Item(Item {
|
||||||
kind: ItemKind::Trait(_, _, _, self_bounds, _),
|
kind: ItemKind::Trait(_, _, _, _, self_bounds, _),
|
||||||
..
|
..
|
||||||
})) = cx.tcx.hir_get_if_local(*def_id)
|
})) = 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);
|
let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id);
|
||||||
|
|
||||||
match item.kind {
|
match item.kind {
|
||||||
ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _, _) => self.check_ty(
|
ItemKind::Static(_, ty, _, _) | ItemKind::Const(_, ty, _, _) => self.check_ty(
|
||||||
cx,
|
cx,
|
||||||
ty,
|
ty,
|
||||||
CheckTyContext {
|
CheckTyContext {
|
||||||
|
|
|
@ -381,7 +381,7 @@ impl UnconditionalRecursion {
|
||||||
implemented_ty_id,
|
implemented_ty_id,
|
||||||
method_span,
|
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 {
|
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() {
|
if attr.is_doc_comment() {
|
||||||
return acc;
|
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()) {
|
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::Crate(parent_mod) => comment_start_before_item_in_mod(cx, parent_mod, parent_mod.spans.inner_span, item),
|
||||||
Node::Item(parent_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)
|
comment_start_before_item_in_mod(cx, parent_mod, parent_item.span, item)
|
||||||
} else {
|
} else {
|
||||||
// Doesn't support impls in this position. Pretend a comment was found.
|
// 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 {
|
match parent_node {
|
||||||
Node::Crate(mod_) => return Some(mod_.spans.inner_span),
|
Node::Crate(mod_) => return Some(mod_.spans.inner_span),
|
||||||
Node::Item(hir::Item {
|
Node::Item(hir::Item {
|
||||||
kind: ItemKind::Mod(mod_),
|
kind: ItemKind::Mod(_, mod_),
|
||||||
span,
|
span,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
|
|
|
@ -130,9 +130,9 @@ impl LateLintPass<'_> for UnnecessaryBoxReturns {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
|
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;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
|
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 assoc_item = cx.tcx.associated_item(impl_item.owner_id);
|
||||||
let contains_todo = |cx, body: &'_ Body<'_>| -> bool {
|
let contains_todo = |cx, body: &'_ Body<'_>| -> bool {
|
||||||
clippy_utils::visitors::for_each_expr_without_closures(body.value, |e| {
|
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 {
|
impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||||
if !item.span.in_external_macro(cx.sess().source_map())
|
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
|
// Ignore imports that already use Underscore
|
||||||
&& item.ident.name != kw::Underscore
|
&& ident.name != kw::Underscore
|
||||||
// Only check traits
|
// Only check traits
|
||||||
&& let Some(Res::Def(DefKind::Trait, _)) = path.res.first()
|
&& let Some(Res::Def(DefKind::Trait, _)) = path.res.first()
|
||||||
&& cx.tcx.maybe_unused_trait_imports(()).contains(&item.owner_id.def_id)
|
&& 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)
|
&& self.msrv.meets(cx, msrvs::UNDERSCORE_IMPORTS)
|
||||||
&& !is_from_proc_macro(cx, &last_segment.ident)
|
&& !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(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
UNUSED_TRAIT_NAMES,
|
UNUSED_TRAIT_NAMES,
|
||||||
|
|
|
@ -230,6 +230,8 @@ impl<'tcx> Delegate<'tcx> for MutationVisitor<'tcx> {
|
||||||
|
|
||||||
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||||
|
|
||||||
|
fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||||
|
|
||||||
fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: 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 {
|
if call_to_unwrap == unwrappable.safe_to_unwrap {
|
||||||
let is_entire_condition = unwrappable.is_entire_condition;
|
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 {
|
let suggested_pattern = if call_to_unwrap {
|
||||||
unwrappable.kind.success_variant_pattern()
|
unwrappable.kind.success_variant_pattern()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -131,11 +131,11 @@ impl LateLintPass<'_> for UpperCaseAcronyms {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
match it.kind {
|
match it.kind {
|
||||||
ItemKind::TyAlias(..) | ItemKind::Struct(..) | ItemKind::Trait(..) => {
|
ItemKind::TyAlias(ident, ..) | ItemKind::Struct(ident, ..) | ItemKind::Trait(_, _, ident, ..) => {
|
||||||
check_ident(cx, &it.ident, it.hir_id(), self.upper_case_acronyms_aggressive);
|
check_ident(cx, &ident, it.hir_id(), self.upper_case_acronyms_aggressive);
|
||||||
},
|
},
|
||||||
ItemKind::Enum(ref enumdef, _) => {
|
ItemKind::Enum(ident, ref enumdef, _) => {
|
||||||
check_ident(cx, &it.ident, it.hir_id(), self.upper_case_acronyms_aggressive);
|
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
|
// 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
|
// the fn check_variant does not know about the vis of the enum of its variants
|
||||||
enumdef.variants.iter().for_each(|variant| {
|
enumdef.variants.iter().for_each(|variant| {
|
||||||
|
|
|
@ -426,6 +426,11 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
||||||
kind!("Tup({elements})");
|
kind!("Tup({elements})");
|
||||||
self.slice(elements, |e| self.expr(e));
|
self.slice(elements, |e| self.expr(e));
|
||||||
},
|
},
|
||||||
|
ExprKind::Use(expr, _) => {
|
||||||
|
bind!(self, expr);
|
||||||
|
kind!("Use({expr})");
|
||||||
|
self.expr(expr);
|
||||||
|
},
|
||||||
ExprKind::Binary(op, left, right) => {
|
ExprKind::Binary(op, left, right) => {
|
||||||
bind!(self, op, left, right);
|
bind!(self, op, left, right);
|
||||||
kind!("Binary({op}, {left}, {right})");
|
kind!("Binary({op}, {left}, {right})");
|
||||||
|
@ -488,6 +493,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
||||||
}) => {
|
}) => {
|
||||||
let capture_clause = match capture_clause {
|
let capture_clause = match capture_clause {
|
||||||
CaptureBy::Value { .. } => "Value { .. }",
|
CaptureBy::Value { .. } => "Value { .. }",
|
||||||
|
CaptureBy::Use { .. } => "Use { .. }",
|
||||||
CaptureBy::Ref => "Ref",
|
CaptureBy::Ref => "Ref",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -787,7 +793,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
|
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
|
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 {
|
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
|
get_attr(cx.sess(), attrs, "dump").count() > 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,11 +44,10 @@ impl AlmostStandardFormulation {
|
||||||
impl<'tcx> LateLintPass<'tcx> for AlmostStandardFormulation {
|
impl<'tcx> LateLintPass<'tcx> for AlmostStandardFormulation {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||||
let mut check_next = false;
|
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
|
let lines = cx
|
||||||
.tcx
|
.tcx
|
||||||
.hir()
|
.hir_attrs(item.hir_id())
|
||||||
.attrs(item.hir_id())
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|attr| Attribute::doc_str(attr).map(|sym| (sym, attr)));
|
.filter_map(|attr| Attribute::doc_str(attr).map(|sym| (sym, attr)));
|
||||||
if is_lint_ref_type(cx, ty) {
|
if is_lint_ref_type(cx, ty) {
|
||||||
|
|
|
@ -104,7 +104,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
|
||||||
return;
|
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) {
|
if is_lint_ref_type(cx, ty) {
|
||||||
check_invalid_clippy_version_attribute(cx, item);
|
check_invalid_clippy_version_attribute(cx, item);
|
||||||
|
|
||||||
|
@ -133,10 +133,10 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
|
||||||
cx,
|
cx,
|
||||||
DEFAULT_LINT,
|
DEFAULT_LINT,
|
||||||
item.span,
|
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) {
|
} 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
|
/// This function extracts the version value of a `clippy::version` attribute if the given value has
|
||||||
/// one
|
/// one
|
||||||
pub(super) fn extract_clippy_version_value(cx: &LateContext<'_>, item: &'_ Item<'_>) -> Option<Symbol> {
|
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| {
|
attrs.iter().find_map(|attr| {
|
||||||
if let hir::Attribute::Unparsed(attr_kind) = &attr
|
if let hir::Attribute::Unparsed(attr_kind) = &attr
|
||||||
// Identify attribute
|
// Identify attribute
|
||||||
|
|
|
@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain:
|
||||||
|
|
||||||
<!-- begin autogenerated nightly -->
|
<!-- begin autogenerated nightly -->
|
||||||
```
|
```
|
||||||
nightly-2025-02-27
|
nightly-2025-03-20
|
||||||
```
|
```
|
||||||
<!-- end autogenerated nightly -->
|
<!-- end autogenerated nightly -->
|
||||||
|
|
||||||
|
|
|
@ -364,6 +364,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
||||||
generics: lg,
|
generics: lg,
|
||||||
contract: lc,
|
contract: lc,
|
||||||
body: lb,
|
body: lb,
|
||||||
|
define_opaque: _,
|
||||||
}),
|
}),
|
||||||
Fn(box ast::Fn {
|
Fn(box ast::Fn {
|
||||||
defaultness: rd,
|
defaultness: rd,
|
||||||
|
@ -371,6 +372,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
||||||
generics: rg,
|
generics: rg,
|
||||||
contract: rc,
|
contract: rc,
|
||||||
body: rb,
|
body: rb,
|
||||||
|
define_opaque: _,
|
||||||
}),
|
}),
|
||||||
) => {
|
) => {
|
||||||
eq_defaultness(*ld, *rd)
|
eq_defaultness(*ld, *rd)
|
||||||
|
@ -502,6 +504,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
|
||||||
generics: lg,
|
generics: lg,
|
||||||
contract: lc,
|
contract: lc,
|
||||||
body: lb,
|
body: lb,
|
||||||
|
define_opaque: _,
|
||||||
}),
|
}),
|
||||||
Fn(box ast::Fn {
|
Fn(box ast::Fn {
|
||||||
defaultness: rd,
|
defaultness: rd,
|
||||||
|
@ -509,6 +512,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
|
||||||
generics: rg,
|
generics: rg,
|
||||||
contract: rc,
|
contract: rc,
|
||||||
body: rb,
|
body: rb,
|
||||||
|
define_opaque: _,
|
||||||
}),
|
}),
|
||||||
) => {
|
) => {
|
||||||
eq_defaultness(*ld, *rd)
|
eq_defaultness(*ld, *rd)
|
||||||
|
@ -567,6 +571,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
|
||||||
generics: lg,
|
generics: lg,
|
||||||
contract: lc,
|
contract: lc,
|
||||||
body: lb,
|
body: lb,
|
||||||
|
define_opaque: _,
|
||||||
}),
|
}),
|
||||||
Fn(box ast::Fn {
|
Fn(box ast::Fn {
|
||||||
defaultness: rd,
|
defaultness: rd,
|
||||||
|
@ -574,6 +579,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
|
||||||
generics: rg,
|
generics: rg,
|
||||||
contract: rc,
|
contract: rc,
|
||||||
body: rb,
|
body: rb,
|
||||||
|
define_opaque: _,
|
||||||
}),
|
}),
|
||||||
) => {
|
) => {
|
||||||
eq_defaultness(*ld, *rd)
|
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 {
|
pub fn eq_where_predicate(l: &WherePredicate, r: &WherePredicate) -> bool {
|
||||||
use WherePredicateKind::*;
|
use WherePredicateKind::*;
|
||||||
match (&l.kind, &r.kind) {
|
over(&l.attrs, &r.attrs, eq_attr)
|
||||||
(BoundPredicate(l), BoundPredicate(r)) => {
|
&& match (&l.kind, &r.kind) {
|
||||||
over(&l.bound_generic_params, &r.bound_generic_params, |l, r| {
|
(BoundPredicate(l), BoundPredicate(r)) => {
|
||||||
eq_generic_param(l, r)
|
over(&l.bound_generic_params, &r.bound_generic_params, |l, r| {
|
||||||
}) && eq_ty(&l.bounded_ty, &r.bounded_ty)
|
eq_generic_param(l, r)
|
||||||
&& over(&l.bounds, &r.bounds, eq_generic_bound)
|
}) && 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)
|
(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,
|
(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 {
|
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) {
|
fn item_search_pat(item: &Item<'_>) -> (Pat, Pat) {
|
||||||
let (start_pat, end_pat) = match &item.kind {
|
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::Static(..) => (Pat::Str("static"), Pat::Str(";")),
|
||||||
ItemKind::Const(..) => (Pat::Str("const"), Pat::Str(";")),
|
ItemKind::Const(..) => (Pat::Str("const"), Pat::Str(";")),
|
||||||
ItemKind::Fn { sig, .. } => (fn_header_search_pat(sig.header), Pat::Str("")),
|
ItemKind::Fn { sig, .. } => (fn_header_search_pat(sig.header), Pat::Str("")),
|
||||||
ItemKind::ForeignMod { .. } => (Pat::Str("extern"), Pat::Str("}")),
|
ItemKind::ForeignMod { .. } => (Pat::Str("extern"), Pat::Str("}")),
|
||||||
ItemKind::TyAlias(..) => (Pat::Str("type"), Pat::Str(";")),
|
ItemKind::TyAlias(..) => (Pat::Str("type"), Pat::Str(";")),
|
||||||
ItemKind::Enum(..) => (Pat::Str("enum"), 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::Struct(..) => (Pat::Str("struct"), Pat::Str(";")),
|
||||||
ItemKind::Union(..) => (Pat::Str("union"), Pat::Str("}")),
|
ItemKind::Union(..) => (Pat::Str("union"), Pat::Str("}")),
|
||||||
ItemKind::Trait(_, Safety::Unsafe, ..)
|
ItemKind::Trait(_, Safety::Unsafe, ..)
|
||||||
|
|
|
@ -291,6 +291,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
|
||||||
ExprKind::ConstBlock(_)
|
ExprKind::ConstBlock(_)
|
||||||
| ExprKind::Array(_)
|
| ExprKind::Array(_)
|
||||||
| ExprKind::Tup(_)
|
| ExprKind::Tup(_)
|
||||||
|
| ExprKind::Use(..)
|
||||||
| ExprKind::Lit(_)
|
| ExprKind::Lit(_)
|
||||||
| ExprKind::Cast(..)
|
| ExprKind::Cast(..)
|
||||||
| ExprKind::Type(..)
|
| ExprKind::Type(..)
|
||||||
|
|
|
@ -393,6 +393,7 @@ impl HirEqInterExpr<'_, '_, '_> {
|
||||||
&& over(lf, rf, |l, r| self.eq_expr_field(l, r))
|
&& 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::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::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::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),
|
(&ExprKind::Yield(le, _), &ExprKind::Yield(re, _)) => return self.eq_expr(le, re),
|
||||||
|
@ -425,6 +426,7 @@ impl HirEqInterExpr<'_, '_, '_> {
|
||||||
| &ExprKind::Ret(..)
|
| &ExprKind::Ret(..)
|
||||||
| &ExprKind::Struct(..)
|
| &ExprKind::Struct(..)
|
||||||
| &ExprKind::Tup(..)
|
| &ExprKind::Tup(..)
|
||||||
|
| &ExprKind::Use(..)
|
||||||
| &ExprKind::Type(..)
|
| &ExprKind::Type(..)
|
||||||
| &ExprKind::Unary(..)
|
| &ExprKind::Unary(..)
|
||||||
| &ExprKind::Yield(..)
|
| &ExprKind::Yield(..)
|
||||||
|
@ -1053,6 +1055,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||||
ExprKind::Tup(tup) => {
|
ExprKind::Tup(tup) => {
|
||||||
self.hash_exprs(tup);
|
self.hash_exprs(tup);
|
||||||
},
|
},
|
||||||
|
ExprKind::Use(expr, _) => {
|
||||||
|
self.hash_expr(expr);
|
||||||
|
},
|
||||||
ExprKind::Unary(lop, le) => {
|
ExprKind::Unary(lop, le) => {
|
||||||
std::mem::discriminant(&lop).hash(&mut self.s);
|
std::mem::discriminant(&lop).hash(&mut self.s);
|
||||||
self.hash_expr(le);
|
self.hash_expr(le);
|
||||||
|
@ -1108,14 +1113,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
||||||
pub fn hash_ty_pat(&mut self, pat: &TyPat<'_>) {
|
pub fn hash_ty_pat(&mut self, pat: &TyPat<'_>) {
|
||||||
std::mem::discriminant(&pat.kind).hash(&mut self.s);
|
std::mem::discriminant(&pat.kind).hash(&mut self.s);
|
||||||
match pat.kind {
|
match pat.kind {
|
||||||
TyPatKind::Range(s, e, i) => {
|
TyPatKind::Range(s, e) => {
|
||||||
if let Some(s) = s {
|
self.hash_const_arg(s);
|
||||||
self.hash_const_arg(s);
|
self.hash_const_arg(e);
|
||||||
}
|
|
||||||
if let Some(e) = e {
|
|
||||||
self.hash_const_arg(e);
|
|
||||||
}
|
|
||||||
std::mem::discriminant(&i).hash(&mut self.s);
|
|
||||||
},
|
},
|
||||||
TyPatKind::Err(_) => {},
|
TyPatKind::Err(_) => {},
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
// (Currently there is no way to opt into sysroot crates without `extern crate`.)
|
// (Currently there is no way to opt into sysroot crates without `extern crate`.)
|
||||||
extern crate rustc_abi;
|
extern crate rustc_abi;
|
||||||
extern crate rustc_ast;
|
extern crate rustc_ast;
|
||||||
extern crate rustc_ast_pretty;
|
|
||||||
extern crate rustc_attr_parsing;
|
extern crate rustc_attr_parsing;
|
||||||
extern crate rustc_const_eval;
|
extern crate rustc_const_eval;
|
||||||
extern crate rustc_data_structures;
|
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 root_mod;
|
||||||
let item_kind = match tcx.hir_node_by_def_id(local_id) {
|
let item_kind = match tcx.hir_node_by_def_id(local_id) {
|
||||||
Node::Crate(r#mod) => {
|
Node::Crate(r#mod) => {
|
||||||
root_mod = ItemKind::Mod(r#mod);
|
root_mod = ItemKind::Mod(Ident::dummy(), r#mod);
|
||||||
&root_mod
|
&root_mod
|
||||||
},
|
},
|
||||||
Node::Item(item) => &item.kind,
|
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 {
|
match item_kind {
|
||||||
ItemKind::Mod(r#mod) => r#mod
|
ItemKind::Mod(_, r#mod) => r#mod
|
||||||
.item_ids
|
.item_ids
|
||||||
.iter()
|
.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(),
|
.collect(),
|
||||||
ItemKind::Impl(r#impl) => r#impl
|
ItemKind::Impl(r#impl) => r#impl
|
||||||
.items
|
.items
|
||||||
|
@ -1130,6 +1132,7 @@ pub fn can_move_expr_to_closure_no_visit<'tcx>(
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum CaptureKind {
|
pub enum CaptureKind {
|
||||||
Value,
|
Value,
|
||||||
|
Use,
|
||||||
Ref(Mutability),
|
Ref(Mutability),
|
||||||
}
|
}
|
||||||
impl CaptureKind {
|
impl CaptureKind {
|
||||||
|
@ -1142,6 +1145,7 @@ impl std::ops::BitOr for CaptureKind {
|
||||||
fn bitor(self, rhs: Self) -> Self::Output {
|
fn bitor(self, rhs: Self) -> Self::Output {
|
||||||
match (self, rhs) {
|
match (self, rhs) {
|
||||||
(CaptureKind::Value, _) | (_, CaptureKind::Value) => CaptureKind::Value,
|
(CaptureKind::Value, _) | (_, CaptureKind::Value) => CaptureKind::Value,
|
||||||
|
(CaptureKind::Use, _) | (_, CaptureKind::Use) => CaptureKind::Use,
|
||||||
(CaptureKind::Ref(Mutability::Mut), CaptureKind::Ref(_))
|
(CaptureKind::Ref(Mutability::Mut), CaptureKind::Ref(_))
|
||||||
| (CaptureKind::Ref(_), CaptureKind::Ref(Mutability::Mut)) => CaptureKind::Ref(Mutability::Mut),
|
| (CaptureKind::Ref(_), CaptureKind::Ref(Mutability::Mut)) => CaptureKind::Ref(Mutability::Mut),
|
||||||
(CaptureKind::Ref(Mutability::Not), CaptureKind::Ref(Mutability::Not)) => CaptureKind::Ref(Mutability::Not),
|
(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
|
pat.each_binding_or_first(&mut |_, id, span, _| match cx
|
||||||
.typeck_results()
|
.typeck_results()
|
||||||
.extract_binding_mode(cx.sess(), id, span)
|
.extract_binding_mode(cx.sess(), id, span)
|
||||||
.unwrap()
|
|
||||||
.0
|
.0
|
||||||
{
|
{
|
||||||
ByRef::No if !is_copy(cx, cx.typeck_results().node_type(id)) => {
|
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) => {
|
ExprKind::Let(let_expr) => {
|
||||||
let mutability = match pat_capture_kind(cx, let_expr.pat) {
|
let mutability = match pat_capture_kind(cx, let_expr.pat) {
|
||||||
CaptureKind::Value => Mutability::Not,
|
CaptureKind::Value | CaptureKind::Use => Mutability::Not,
|
||||||
CaptureKind::Ref(m) => m,
|
CaptureKind::Ref(m) => m,
|
||||||
};
|
};
|
||||||
return CaptureKind::Ref(mutability);
|
return CaptureKind::Ref(mutability);
|
||||||
|
@ -1231,7 +1234,7 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind {
|
||||||
let mut mutability = Mutability::Not;
|
let mut mutability = Mutability::Not;
|
||||||
for capture in arms.iter().map(|arm| pat_capture_kind(cx, arm.pat)) {
|
for capture in arms.iter().map(|arm| pat_capture_kind(cx, arm.pat)) {
|
||||||
match capture {
|
match capture {
|
||||||
CaptureKind::Value => break,
|
CaptureKind::Value | CaptureKind::Use => break,
|
||||||
CaptureKind::Ref(Mutability::Mut) => mutability = Mutability::Mut,
|
CaptureKind::Ref(Mutability::Mut) => mutability = Mutability::Mut,
|
||||||
CaptureKind::Ref(Mutability::Not) => (),
|
CaptureKind::Ref(Mutability::Not) => (),
|
||||||
}
|
}
|
||||||
|
@ -1241,7 +1244,7 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind {
|
||||||
_ => break,
|
_ => break,
|
||||||
},
|
},
|
||||||
Node::LetStmt(l) => match pat_capture_kind(cx, l.pat) {
|
Node::LetStmt(l) => match pat_capture_kind(cx, l.pat) {
|
||||||
CaptureKind::Value => break,
|
CaptureKind::Value | CaptureKind::Use => break,
|
||||||
capture @ CaptureKind::Ref(_) => return capture,
|
capture @ CaptureKind::Ref(_) => return capture,
|
||||||
},
|
},
|
||||||
_ => break,
|
_ => 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) {
|
if !self.locals.contains(&local_id) {
|
||||||
let capture = match capture.info.capture_kind {
|
let capture = match capture.info.capture_kind {
|
||||||
UpvarCapture::ByValue => CaptureKind::Value,
|
UpvarCapture::ByValue => CaptureKind::Value,
|
||||||
|
UpvarCapture::ByUse => CaptureKind::Use,
|
||||||
UpvarCapture::ByRef(kind) => match kind {
|
UpvarCapture::ByRef(kind) => match kind {
|
||||||
BorrowKind::Immutable => CaptureKind::Ref(Mutability::Not),
|
BorrowKind::Immutable => CaptureKind::Ref(Mutability::Not),
|
||||||
BorrowKind::UniqueImmutable | BorrowKind::Mutable => {
|
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> {
|
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;
|
let parent_id = cx.tcx.hir_get_parent_item(expr.hir_id).def_id;
|
||||||
match cx.tcx.hir_node_by_def_id(parent_id) {
|
match cx.tcx.hir_node_by_def_id(parent_id) {
|
||||||
Node::Item(Item { ident, .. })
|
Node::Item(item) => item.kind.ident().map(|ident| ident.name),
|
||||||
| Node::TraitItem(TraitItem { ident, .. })
|
Node::TraitItem(TraitItem { ident, .. }) | Node::ImplItem(ImplItem { ident, .. }) => Some(ident.name),
|
||||||
| Node::ImplItem(ImplItem { ident, .. }) => Some(ident.name),
|
|
||||||
_ => None,
|
_ => 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 {
|
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 {
|
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 prev_enclosing_node = None;
|
||||||
let mut enclosing_node = node;
|
let mut enclosing_node = node;
|
||||||
while Some(enclosing_node) != prev_enclosing_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;
|
return true;
|
||||||
}
|
}
|
||||||
prev_enclosing_node = Some(enclosing_node);
|
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(_))))
|
.filter(|(_, node)| matches!(node, OwnerNode::Item(item) if matches!(item.kind, ItemKind::Impl(_))))
|
||||||
.any(|(id, _)| {
|
.any(|(id, _)| {
|
||||||
has_attr(
|
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,
|
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 {
|
pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
|
||||||
cx.tcx
|
cx.tcx
|
||||||
.hir()
|
.hir_attrs(hir::CRATE_HIR_ID)
|
||||||
.attrs(hir::CRATE_HIR_ID)
|
|
||||||
.iter()
|
.iter()
|
||||||
.any(|attr| attr.name_or_empty() == sym::no_std)
|
.any(|attr| attr.name_or_empty() == sym::no_std)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
|
pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
|
||||||
cx.tcx
|
cx.tcx
|
||||||
.hir()
|
.hir_attrs(hir::CRATE_HIR_ID)
|
||||||
.attrs(hir::CRATE_HIR_ID)
|
|
||||||
.iter()
|
.iter()
|
||||||
.any(|attr| attr.name_or_empty() == sym::no_core)
|
.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) {
|
for id in tcx.hir_module_free_items(module) {
|
||||||
if matches!(tcx.def_kind(id.owner_id), DefKind::Const)
|
if matches!(tcx.def_kind(id.owner_id), DefKind::Const)
|
||||||
&& let item = tcx.hir_item(id)
|
&& 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 {
|
if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
|
||||||
// We could also check for the type name `test::TestDescAndFn`
|
// We could also check for the type name `test::TestDescAndFn`
|
||||||
if let Res::Def(DefKind::Struct, _) = path.res {
|
if let Res::Def(DefKind::Struct, _) = path.res {
|
||||||
let has_test_marker = tcx
|
let has_test_marker = tcx
|
||||||
.hir()
|
.hir_attrs(item.hir_id())
|
||||||
.attrs(item.hir_id())
|
|
||||||
.iter()
|
.iter()
|
||||||
.any(|a| a.has_name(sym::rustc_test_marker));
|
.any(|a| a.has_name(sym::rustc_test_marker));
|
||||||
if has_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
|
// function scope
|
||||||
.any(|(_id, node)| {
|
.any(|(_id, node)| {
|
||||||
if let Node::Item(item) = 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,
|
// Note that we have sorted the item names in the visitor,
|
||||||
// so the binary_search gets the same as `contains`, but faster.
|
// 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
|
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
|
/// This only checks directly applied attributes, to see if a node is inside a `#[cfg(test)]` parent
|
||||||
/// use [`is_in_cfg_test`]
|
/// use [`is_in_cfg_test`]
|
||||||
pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool {
|
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)
|
if attr.has_name(sym::cfg)
|
||||||
&& let Some(items) = attr.meta_item_list()
|
&& let Some(items) = attr.meta_item_list()
|
||||||
&& let [item] = &*items
|
&& 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.
|
/// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied.
|
||||||
pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
||||||
let hir = tcx.hir();
|
|
||||||
|
|
||||||
tcx.has_attr(def_id, sym::cfg)
|
tcx.has_attr(def_id, sym::cfg)
|
||||||
|| tcx
|
|| tcx
|
||||||
.hir_parent_iter(tcx.local_def_id_to_hir_id(def_id))
|
.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))
|
.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
|
// a::b::c ::d::sym refers to
|
||||||
// e::f::sym:: ::
|
// e::f::sym:: ::
|
||||||
// result should be super::super::super::super::e::f
|
// 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());
|
path.push(s.to_string());
|
||||||
}
|
}
|
||||||
if let DefPathData::TypeNs(_) = r {
|
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
|
// a::b::sym:: :: refers to
|
||||||
// c::d::e ::f::sym
|
// c::d::e ::f::sym
|
||||||
// when looking at `f`
|
// when looking at `f`
|
||||||
Left(DefPathData::TypeNs(sym)) => path.push(sym.to_string()),
|
Left(DefPathData::TypeNs(Some(sym))) => path.push(sym.to_string()),
|
||||||
// consider:
|
// consider:
|
||||||
// a::b::c ::d::sym refers to
|
// a::b::c ::d::sym refers to
|
||||||
// e::f::sym:: ::
|
// 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
|
// `super` chain would be too long, just use the absolute path instead
|
||||||
once(String::from("crate"))
|
once(String::from("crate"))
|
||||||
.chain(to.data.iter().filter_map(|el| {
|
.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())
|
Some(sym.to_string())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#![allow(clippy::similar_names)] // `expr` and `expn`
|
#![allow(clippy::similar_names)] // `expr` and `expn`
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, OnceLock};
|
||||||
|
|
||||||
use crate::get_unique_attr;
|
use crate::get_unique_attr;
|
||||||
use crate::visitors::{Descend, for_each_expr_without_closures};
|
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 arrayvec::ArrayVec;
|
||||||
use rustc_ast::{FormatArgs, FormatArgument, FormatPlaceholder};
|
use rustc_ast::{FormatArgs, FormatArgument, FormatPlaceholder};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
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_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath};
|
||||||
use rustc_lint::{LateContext, LintContext};
|
use rustc_lint::{LateContext, LintContext};
|
||||||
use rustc_span::def_id::DefId;
|
use rustc_span::def_id::DefId;
|
||||||
|
|
|
@ -6,8 +6,7 @@ use rustc_index::bit_set::DenseBitSet;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::mir::visit::Visitor as _;
|
use rustc_middle::mir::visit::Visitor as _;
|
||||||
use rustc_middle::mir::{self, Mutability};
|
use rustc_middle::mir::{self, Mutability};
|
||||||
use rustc_middle::ty::visit::TypeVisitor;
|
use rustc_middle::ty::{self, TyCtxt, TypeVisitor};
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
|
||||||
use rustc_mir_dataflow::impls::MaybeStorageLive;
|
use rustc_mir_dataflow::impls::MaybeStorageLive;
|
||||||
use rustc_mir_dataflow::{Analysis, ResultsCursor};
|
use rustc_mir_dataflow::{Analysis, ResultsCursor};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
|
@ -109,7 +109,7 @@ impl Msrv {
|
||||||
let start = cx.last_node_with_lint_attrs;
|
let start = cx.last_node_with_lint_attrs;
|
||||||
if let Some(msrv_attr) = once(start)
|
if let Some(msrv_attr) = once(start)
|
||||||
.chain(cx.tcx.hir_parent_id_iter(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);
|
return Some(msrv_attr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,8 @@
|
||||||
use crate::source::{snippet, snippet_opt, snippet_with_applicability, snippet_with_context};
|
use crate::source::{snippet, snippet_opt, snippet_with_applicability, snippet_with_context};
|
||||||
use crate::ty::expr_sig;
|
use crate::ty::expr_sig;
|
||||||
use crate::{get_parent_expr_for_hir, higher};
|
use crate::{get_parent_expr_for_hir, higher};
|
||||||
|
use rustc_ast::ast;
|
||||||
use rustc_ast::util::parser::AssocOp;
|
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_errors::Applicability;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::{Closure, ExprKind, HirId, MutTy, TyKind};
|
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.
|
/// 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 {
|
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) {
|
if let Some(range) = higher::Range::hir(expr) {
|
||||||
let op = match range.limits {
|
let op = AssocOp::Range(range.limits);
|
||||||
ast::RangeLimits::HalfOpen => AssocOp::DotDot,
|
|
||||||
ast::RangeLimits::Closed => AssocOp::DotDotEq,
|
|
||||||
};
|
|
||||||
let start = range.start.map_or("".into(), |expr| get_snippet(expr.span));
|
let start = range.start.map_or("".into(), |expr| get_snippet(expr.span));
|
||||||
let end = range.end.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::Become(..)
|
||||||
| ExprKind::Struct(..)
|
| ExprKind::Struct(..)
|
||||||
| ExprKind::Tup(..)
|
| ExprKind::Tup(..)
|
||||||
|
| ExprKind::Use(..)
|
||||||
| ExprKind::Err(_)
|
| ExprKind::Err(_)
|
||||||
| ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(get_snippet(expr.span)),
|
| ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(get_snippet(expr.span)),
|
||||||
ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet),
|
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))
|
Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span))
|
||||||
},
|
},
|
||||||
ExprKind::AssignOp(op, lhs, rhs) => {
|
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(
|
ExprKind::Binary(op, lhs, rhs) => Sugg::BinOp(
|
||||||
AssocOp::from_ast_binop(op.node),
|
AssocOp::Binary(op.node),
|
||||||
get_snippet(lhs.span),
|
get_snippet(lhs.span),
|
||||||
get_snippet(rhs.span),
|
get_snippet(rhs.span),
|
||||||
),
|
),
|
||||||
ExprKind::Cast(lhs, ty) |
|
ExprKind::Cast(lhs, ty) |
|
||||||
//FIXME(chenyukang), remove this after type ascription is removed from AST
|
//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,
|
ctxt: SyntaxContext,
|
||||||
app: &mut Applicability,
|
app: &mut Applicability,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
use rustc_ast::ast::RangeLimits;
|
|
||||||
|
|
||||||
let mut snippet = |span: Span| snippet_with_context(cx, span, ctxt, default, app).0;
|
let mut snippet = |span: Span| snippet_with_context(cx, span, ctxt, default, app).0;
|
||||||
|
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
|
@ -223,19 +218,15 @@ impl<'a> Sugg<'a> {
|
||||||
| ast::ExprKind::Try(..)
|
| ast::ExprKind::Try(..)
|
||||||
| ast::ExprKind::TryBlock(..)
|
| ast::ExprKind::TryBlock(..)
|
||||||
| ast::ExprKind::Tup(..)
|
| ast::ExprKind::Tup(..)
|
||||||
|
| ast::ExprKind::Use(..)
|
||||||
| ast::ExprKind::Array(..)
|
| ast::ExprKind::Array(..)
|
||||||
| ast::ExprKind::While(..)
|
| ast::ExprKind::While(..)
|
||||||
| ast::ExprKind::Await(..)
|
| ast::ExprKind::Await(..)
|
||||||
| ast::ExprKind::Err(_)
|
| ast::ExprKind::Err(_)
|
||||||
| ast::ExprKind::Dummy
|
| ast::ExprKind::Dummy
|
||||||
| ast::ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(snippet(expr.span)),
|
| ast::ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(snippet(expr.span)),
|
||||||
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp(
|
ast::ExprKind::Range(ref lhs, ref rhs, limits) => Sugg::BinOp(
|
||||||
AssocOp::DotDot,
|
AssocOp::Range(limits),
|
||||||
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,
|
|
||||||
lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)),
|
lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)),
|
||||||
rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)),
|
rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)),
|
||||||
),
|
),
|
||||||
|
@ -245,19 +236,19 @@ impl<'a> Sugg<'a> {
|
||||||
snippet(rhs.span),
|
snippet(rhs.span),
|
||||||
),
|
),
|
||||||
ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => Sugg::BinOp(
|
ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => Sugg::BinOp(
|
||||||
astbinop2assignop(op),
|
AssocOp::AssignOp(op.node),
|
||||||
snippet(lhs.span),
|
snippet(lhs.span),
|
||||||
snippet(rhs.span),
|
snippet(rhs.span),
|
||||||
),
|
),
|
||||||
ast::ExprKind::Binary(op, ref lhs, ref rhs) => Sugg::BinOp(
|
ast::ExprKind::Binary(op, ref lhs, ref rhs) => Sugg::BinOp(
|
||||||
AssocOp::from_ast_binop(op.node),
|
AssocOp::Binary(op.node),
|
||||||
snippet(lhs.span),
|
snippet(lhs.span),
|
||||||
snippet(rhs.span),
|
snippet(rhs.span),
|
||||||
),
|
),
|
||||||
ast::ExprKind::Cast(ref lhs, ref ty) |
|
ast::ExprKind::Cast(ref lhs, ref ty) |
|
||||||
//FIXME(chenyukang), remove this after type ascription is removed from AST
|
//FIXME(chenyukang), remove this after type ascription is removed from AST
|
||||||
ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp(
|
ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp(
|
||||||
AssocOp::As,
|
AssocOp::Cast,
|
||||||
snippet(lhs.span),
|
snippet(lhs.span),
|
||||||
snippet(ty.span),
|
snippet(ty.span),
|
||||||
),
|
),
|
||||||
|
@ -276,7 +267,7 @@ impl<'a> Sugg<'a> {
|
||||||
|
|
||||||
/// Convenience method to create the `<lhs> as <rhs>` suggestion.
|
/// Convenience method to create the `<lhs> as <rhs>` suggestion.
|
||||||
pub fn as_ty<R: Display>(self, rhs: R) -> Sugg<'static> {
|
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.
|
/// 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>`
|
/// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>`
|
||||||
/// suggestion.
|
/// suggestion.
|
||||||
pub fn range(self, end: &Self, limit: ast::RangeLimits) -> Sugg<'static> {
|
pub fn range(self, end: &Self, limits: ast::RangeLimits) -> Sugg<'static> {
|
||||||
match limit {
|
make_assoc(AssocOp::Range(limits), &self, end)
|
||||||
ast::RangeLimits::HalfOpen => make_assoc(AssocOp::DotDot, &self, end),
|
|
||||||
ast::RangeLimits::Closed => make_assoc(AssocOp::DotDotEq, &self, end),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds parentheses to any expression that might need them. Suitable to the
|
/// 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.
|
/// Generates a string from the operator and both sides.
|
||||||
fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String {
|
fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String {
|
||||||
match op {
|
match op {
|
||||||
AssocOp::Add
|
AssocOp::Binary(op) => format!("{lhs} {} {rhs}", op.as_str()),
|
||||||
| 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::Assign => format!("{lhs} = {rhs}"),
|
AssocOp::Assign => format!("{lhs} = {rhs}"),
|
||||||
AssocOp::AssignOp(op) => {
|
AssocOp::AssignOp(op) => format!("{lhs} {}= {rhs}", op.as_str()),
|
||||||
format!("{lhs} {}= {rhs}", token_kind_to_string(&token::BinOp(op)))
|
AssocOp::Cast => format!("{lhs} as {rhs}"),
|
||||||
},
|
AssocOp::Range(limits) => format!("{lhs}{}{rhs}", limits.as_str()),
|
||||||
AssocOp::As => format!("{lhs} as {rhs}"),
|
|
||||||
AssocOp::DotDot => format!("{lhs}..{rhs}"),
|
|
||||||
AssocOp::DotDotEq => format!("{lhs}..={rhs}"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,7 +434,7 @@ impl Neg for Sugg<'_> {
|
||||||
type Output = Sugg<'static>;
|
type Output = Sugg<'static>;
|
||||||
fn neg(self) -> Sugg<'static> {
|
fn neg(self) -> Sugg<'static> {
|
||||||
match &self {
|
match &self {
|
||||||
Self::BinOp(AssocOp::As, ..) => Sugg::MaybeParen(format!("-({self})").into()),
|
Self::BinOp(AssocOp::Cast, ..) => Sugg::MaybeParen(format!("-({self})").into()),
|
||||||
_ => make_unop("-", self),
|
_ => make_unop("-", self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -477,16 +443,17 @@ impl Neg for Sugg<'_> {
|
||||||
impl<'a> Not for Sugg<'a> {
|
impl<'a> Not for Sugg<'a> {
|
||||||
type Output = Sugg<'a>;
|
type Output = Sugg<'a>;
|
||||||
fn not(self) -> 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 {
|
if let Sugg::BinOp(op, lhs, rhs) = self {
|
||||||
let to_op = match op {
|
let to_op = match op {
|
||||||
Equal => NotEqual,
|
Binary(Eq) => Binary(Ne),
|
||||||
NotEqual => Equal,
|
Binary(Ne) => Binary(Eq),
|
||||||
Less => GreaterEqual,
|
Binary(Lt) => Binary(Ge),
|
||||||
GreaterEqual => Less,
|
Binary(Ge) => Binary(Lt),
|
||||||
Greater => LessEqual,
|
Binary(Gt) => Binary(Le),
|
||||||
LessEqual => Greater,
|
Binary(Le) => Binary(Gt),
|
||||||
_ => return make_unop("!", Sugg::BinOp(op, lhs, rhs)),
|
_ => return make_unop("!", Sugg::BinOp(op, lhs, rhs)),
|
||||||
};
|
};
|
||||||
Sugg::BinOp(to_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> {
|
pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> {
|
||||||
/// Returns `true` if the operator is a shift operator `<<` or `>>`.
|
/// Returns `true` if the operator is a shift operator `<<` or `>>`.
|
||||||
fn is_shift(op: AssocOp) -> bool {
|
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
|
/// 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 {
|
fn is_arith(op: AssocOp) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
op,
|
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())
|
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> {
|
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)]
|
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||||
|
@ -605,69 +578,17 @@ enum Associativity {
|
||||||
/// associative.
|
/// associative.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn associativity(op: AssocOp) -> Associativity {
|
fn associativity(op: AssocOp) -> Associativity {
|
||||||
use rustc_ast::util::parser::AssocOp::{
|
use ast::BinOpKind::{Add, And, BitAnd, BitOr, BitXor, Div, Eq, Ge, Gt, Le, Lt, Mul, Ne, Or, Rem, Shl, Shr, Sub};
|
||||||
Add, As, Assign, AssignOp, BitAnd, BitOr, BitXor, Divide, DotDot, DotDotEq, Equal, Greater, GreaterEqual, LAnd,
|
use rustc_ast::util::parser::AssocOp::{Assign, AssignOp, Binary, Cast, Range};
|
||||||
LOr, Less, LessEqual, Modulus, Multiply, NotEqual, ShiftLeft, ShiftRight, Subtract,
|
|
||||||
};
|
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
Assign | AssignOp(_) => Associativity::Right,
|
Assign | AssignOp(_) => Associativity::Right,
|
||||||
Add | BitAnd | BitOr | BitXor | LAnd | LOr | Multiply | As => Associativity::Both,
|
Binary(Add | BitAnd | BitOr | BitXor | And | Or | Mul) | Cast => Associativity::Both,
|
||||||
Divide | Equal | Greater | GreaterEqual | Less | LessEqual | Modulus | NotEqual | ShiftLeft | ShiftRight
|
Binary(Div | Eq | Gt | Ge | Lt | Le | Rem | Ne | Shl | Shr | Sub) => Associativity::Left,
|
||||||
| Subtract => Associativity::Left,
|
Range(_) => Associativity::None,
|
||||||
DotDot | DotDotEq => 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]`
|
/// Returns the indentation before `span` if there are nothing but `[ \t]`
|
||||||
/// before it on its line.
|
/// before it on its line.
|
||||||
fn indentation<T: LintContext>(cx: &T, span: Span) -> Option<String> {
|
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> {
|
impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
|
||||||
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
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) {
|
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {
|
||||||
if let PlaceBase::Local(id) = cmt.place.base {
|
if let PlaceBase::Local(id) = cmt.place.base {
|
||||||
let map = self.cx.tcx.hir();
|
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);
|
let mut start_snip = snippet_with_applicability(self.cx, start_span, "..", &mut self.applicability);
|
||||||
|
|
||||||
// identifier referring to the variable currently triggered (i.e.: `fp`)
|
// 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`)
|
// full identifier that includes projection (i.e.: `fp.field`)
|
||||||
let ident_str_with_proj = snippet(self.cx, span, "..").to_string();
|
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
|
// item is used in a call
|
||||||
// i.e.: `Call`: `|x| please(x)` or `MethodCall`: `|x| [1, 2, 3].contains(x)`
|
// i.e.: `Call`: `|x| please(x)` or `MethodCall`: `|x| [1, 2, 3].contains(x)`
|
||||||
ExprKind::Call(_, call_args) | ExprKind::MethodCall(_, _, call_args, _) => {
|
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();
|
let arg_ty_kind = self.cx.typeck_results().expr_ty(expr).kind();
|
||||||
|
|
||||||
if matches!(arg_ty_kind, ty::Ref(_, _, Mutability::Not)) {
|
if matches!(arg_ty_kind, ty::Ref(_, _, Mutability::Not)) {
|
||||||
|
@ -1069,6 +992,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
|
||||||
mod test {
|
mod test {
|
||||||
use super::Sugg;
|
use super::Sugg;
|
||||||
|
|
||||||
|
use rustc_ast as ast;
|
||||||
use rustc_ast::util::parser::AssocOp;
|
use rustc_ast::util::parser::AssocOp;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
@ -1086,15 +1010,15 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn binop_maybe_par() {
|
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());
|
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());
|
assert_eq!("((1 + 1) + (1 + 1))", sugg.maybe_par().to_string());
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn not_op() {
|
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) {
|
fn test_not(op: AssocOp, correct: &str) {
|
||||||
let sugg = Sugg::BinOp(op, "x".into(), "y".into());
|
let sugg = Sugg::BinOp(op, "x".into(), "y".into());
|
||||||
|
@ -1102,16 +1026,16 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invert the comparison operator.
|
// Invert the comparison operator.
|
||||||
test_not(Equal, "x != y");
|
test_not(AssocOp::Binary(Eq), "x != y");
|
||||||
test_not(NotEqual, "x == y");
|
test_not(AssocOp::Binary(Ne), "x == y");
|
||||||
test_not(Less, "x >= y");
|
test_not(AssocOp::Binary(Lt), "x >= y");
|
||||||
test_not(LessEqual, "x > y");
|
test_not(AssocOp::Binary(Le), "x > y");
|
||||||
test_not(Greater, "x <= y");
|
test_not(AssocOp::Binary(Gt), "x <= y");
|
||||||
test_not(GreaterEqual, "x < y");
|
test_not(AssocOp::Binary(Ge), "x < y");
|
||||||
|
|
||||||
// Other operators are inverted like !(..).
|
// Other operators are inverted like !(..).
|
||||||
test_not(Add, "!(x + y)");
|
test_not(AssocOp::Binary(Add), "!(x + y)");
|
||||||
test_not(LAnd, "!(x && y)");
|
test_not(AssocOp::Binary(And), "!(x && y)");
|
||||||
test_not(LOr, "!(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;
|
mod type_certainty;
|
||||||
pub use type_certainty::expr_type_is_certain;
|
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> {
|
pub fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
|
||||||
cx.maybe_typeck_results()
|
cx.maybe_typeck_results()
|
||||||
.and_then(|results| {
|
.and_then(|results| {
|
||||||
|
|
|
@ -66,6 +66,8 @@ impl MutVarsDelegate {
|
||||||
impl<'tcx> Delegate<'tcx> for MutVarsDelegate {
|
impl<'tcx> Delegate<'tcx> for MutVarsDelegate {
|
||||||
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
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) {
|
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, bk: ty::BorrowKind) {
|
||||||
if bk == ty::BorrowKind::Mutable {
|
if bk == ty::BorrowKind::Mutable {
|
||||||
self.update(cmt);
|
self.update(cmt);
|
||||||
|
|
|
@ -648,6 +648,9 @@ pub fn for_each_unconsumed_temporary<'tcx, B>(
|
||||||
helper(typeck, true, arg, f)?;
|
helper(typeck, true, arg, f)?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
ExprKind::Use(expr, _) => {
|
||||||
|
helper(typeck, true, expr, f)?;
|
||||||
|
},
|
||||||
ExprKind::Index(borrowed, consumed, _)
|
ExprKind::Index(borrowed, consumed, _)
|
||||||
| ExprKind::Assign(borrowed, consumed, _)
|
| ExprKind::Assign(borrowed, consumed, _)
|
||||||
| ExprKind::AssignOp(_, borrowed, consumed) => {
|
| ExprKind::AssignOp(_, borrowed, consumed) => {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[toolchain]
|
[toolchain]
|
||||||
# begin autogenerated nightly
|
# begin autogenerated nightly
|
||||||
channel = "nightly-2025-02-27"
|
channel = "nightly-2025-03-20"
|
||||||
# end autogenerated nightly
|
# end autogenerated nightly
|
||||||
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
||||||
profile = "minimal"
|
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`
|
= 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)]`
|
= 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
|
error: you are deriving `Ord` but have implemented `PartialOrd` explicitly
|
||||||
--> tests/ui/derive_ord_xor_partial_ord.rs:33:10
|
--> tests/ui/derive_ord_xor_partial_ord.rs:33:10
|
||||||
|
@ -24,7 +23,6 @@ note: `PartialOrd` implemented here
|
||||||
|
|
|
|
||||||
LL | impl PartialOrd<DeriveOrdWithExplicitTypeVariable> for DeriveOrdWithExplicitTypeVariable {
|
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`
|
error: you are implementing `Ord` explicitly but have derived `PartialOrd`
|
||||||
--> tests/ui/derive_ord_xor_partial_ord.rs:47:1
|
--> tests/ui/derive_ord_xor_partial_ord.rs:47:1
|
||||||
|
@ -42,7 +40,6 @@ note: `PartialOrd` implemented here
|
||||||
|
|
|
|
||||||
LL | #[derive(PartialOrd, PartialEq, Eq)]
|
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`
|
error: you are implementing `Ord` explicitly but have derived `PartialOrd`
|
||||||
--> tests/ui/derive_ord_xor_partial_ord.rs:69:5
|
--> tests/ui/derive_ord_xor_partial_ord.rs:69:5
|
||||||
|
@ -60,7 +57,6 @@ note: `PartialOrd` implemented here
|
||||||
|
|
|
|
||||||
LL | #[derive(PartialOrd, PartialEq, Eq)]
|
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
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ note: `PartialEq` implemented here
|
||||||
LL | impl PartialEq for Bar {
|
LL | impl PartialEq for Bar {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: `#[deny(clippy::derived_hash_with_manual_eq)]` on by default
|
= 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
|
error: you are deriving `Hash` but have implemented `PartialEq` explicitly
|
||||||
--> tests/ui/derived_hash_with_manual_eq.rs:23:10
|
--> tests/ui/derived_hash_with_manual_eq.rs:23:10
|
||||||
|
@ -23,7 +22,6 @@ note: `PartialEq` implemented here
|
||||||
|
|
|
|
||||||
LL | impl PartialEq<Baz> for Baz {
|
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
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,6 @@ error: sub-expression diverges
|
||||||
|
|
|
|
||||||
LL | _ => true || panic!("boo"),
|
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
|
error: sub-expression diverges
|
||||||
--> tests/ui/diverging_sub_expression.rs:52:29
|
--> tests/ui/diverging_sub_expression.rs:52:29
|
||||||
|
|
|
@ -38,7 +38,6 @@ note: potential failure(s)
|
||||||
|
|
|
|
||||||
LL | panic!();
|
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
|
error: consider implementing `TryFrom` instead
|
||||||
--> tests/ui/fallible_impl_from.rs:40:1
|
--> tests/ui/fallible_impl_from.rs:40:1
|
||||||
|
@ -64,7 +63,6 @@ LL | } else if s.parse::<u32>().unwrap() != 42 {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
LL | panic!("{:?}", s);
|
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
|
error: consider implementing `TryFrom` instead
|
||||||
--> tests/ui/fallible_impl_from.rs:60:1
|
--> tests/ui/fallible_impl_from.rs:60:1
|
||||||
|
@ -85,7 +83,6 @@ LL | if s.parse::<u32>().ok().unwrap() != 42 {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
LL | panic!("{:?}", s);
|
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
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ LL | #[derive(Hash)]
|
||||||
= note: ... as (`hash("abc") != hash("abc".as_bytes())`
|
= note: ... as (`hash("abc") != hash("abc".as_bytes())`
|
||||||
= help: consider either removing one of the `Borrow` implementations (`Borrow<str>` or `Borrow<[u8]>`) ...
|
= help: consider either removing one of the `Borrow` implementations (`Borrow<str>` or `Borrow<[u8]>`) ...
|
||||||
= help: ... or not implementing `Hash` for this type
|
= 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
|
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
|
--> tests/ui/impl_hash_with_borrow_str_and_bytes.rs:117:6
|
||||||
|
|
|
@ -192,6 +192,7 @@ impl Atpit for () {
|
||||||
|
|
||||||
type Tait = impl DerefMut;
|
type Tait = impl DerefMut;
|
||||||
//~^ implied_bounds_in_impls
|
//~^ implied_bounds_in_impls
|
||||||
|
#[define_opaque(Tait)]
|
||||||
fn define() -> Tait {
|
fn define() -> Tait {
|
||||||
&mut [] as &mut [()]
|
&mut [] as &mut [()]
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,6 +192,7 @@ impl Atpit for () {
|
||||||
|
|
||||||
type Tait = impl Deref + DerefMut;
|
type Tait = impl Deref + DerefMut;
|
||||||
//~^ implied_bounds_in_impls
|
//~^ implied_bounds_in_impls
|
||||||
|
#[define_opaque(Tait)]
|
||||||
fn define() -> Tait {
|
fn define() -> Tait {
|
||||||
&mut [] as &mut [()]
|
&mut [] as &mut [()]
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,15 +6,12 @@ LL | byte_view(panic!());
|
||||||
|
|
|
|
||||||
= note: `-D clippy::diverging-sub-expression` implied by `-D warnings`
|
= note: `-D clippy::diverging-sub-expression` implied by `-D warnings`
|
||||||
= help: to override `-D warnings` add `#[allow(clippy::diverging_sub_expression)]`
|
= 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
|
error: sub-expression diverges
|
||||||
--> tests/ui/issue-7447.rs:29:19
|
--> tests/ui/issue-7447.rs:29:19
|
||||||
|
|
|
|
||||||
LL | group_entries(panic!());
|
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
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -207,6 +207,7 @@ mod msrv {
|
||||||
mod with_ty_alias {
|
mod with_ty_alias {
|
||||||
type Foo = impl std::fmt::Debug;
|
type Foo = impl std::fmt::Debug;
|
||||||
|
|
||||||
|
#[define_opaque(Foo)]
|
||||||
fn foo(_: Foo) {
|
fn foo(_: Foo) {
|
||||||
let _: Foo = 1;
|
let _: Foo = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ mod issue10041 {
|
||||||
struct Bomb2;
|
struct Bomb2;
|
||||||
|
|
||||||
impl Bomb2 {
|
impl Bomb2 {
|
||||||
|
#[define_opaque(X)]
|
||||||
pub fn new() -> X {
|
pub fn new() -> X {
|
||||||
//~^ ERROR: overflow evaluating the requirement
|
//~^ ERROR: overflow evaluating the requirement
|
||||||
0i32
|
0i32
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0275]: overflow evaluating the requirement `<i32 as std::ops::Add>::Output == issue10041::X`
|
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 {
|
LL | pub fn new() -> X {
|
||||||
| ^
|
| ^
|
||||||
|
|
|
@ -23,7 +23,6 @@ note: existing `clone` defined here
|
||||||
|
|
|
|
||||||
LL | #[derive(Clone)]
|
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
|
error: method's name is the same as an existing method in a trait
|
||||||
--> tests/ui/same_name_method.rs:46:13
|
--> 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