1
Fork 0
r? @ghost

changelog: none
This commit is contained in:
Philipp Krones 2025-03-20 19:52:14 +00:00 committed by GitHub
commit d1d0fee887
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
101 changed files with 380 additions and 453 deletions

View file

@ -6,8 +6,8 @@ use clippy_config::types::{
};
use clippy_utils::diagnostics::span_lint_and_note;
use rustc_hir::{
AssocItemKind, FieldDef, HirId, ImplItemRef, IsAuto, Item, ItemKind, Mod, QPath, TraitItemRef, TyKind, UseKind,
Variant, VariantData,
AssocItemKind, FieldDef, HirId, ImplItemRef, IsAuto, Item, ItemKind, Mod, QPath, TraitItemRef, TyKind, Variant,
VariantData,
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::impl_lint_pass;
@ -202,11 +202,7 @@ impl ArbitrarySourceItemOrdering {
}
/// Produces a linting warning for incorrectly ordered item members.
fn lint_member_name<T: LintContext>(
cx: &T,
ident: &rustc_span::symbol::Ident,
before_ident: &rustc_span::symbol::Ident,
) {
fn lint_member_name<T: LintContext>(cx: &T, ident: &rustc_span::Ident, before_ident: &rustc_span::Ident) {
span_lint_and_note(
cx,
ARBITRARY_SOURCE_ITEM_ORDERING,
@ -218,21 +214,18 @@ impl ArbitrarySourceItemOrdering {
}
fn lint_member_item<T: LintContext>(cx: &T, item: &Item<'_>, before_item: &Item<'_>, msg: &'static str) {
let span = if item.ident.as_str().is_empty() {
&item.span
let span = if let Some(ident) = item.kind.ident() {
ident.span
} else {
&item.ident.span
item.span
};
let (before_span, note) = if before_item.ident.as_str().is_empty() {
(
&before_item.span,
"should be placed before the following item".to_owned(),
)
let (before_span, note) = if let Some(ident) = before_item.kind.ident() {
(ident.span, format!("should be placed before `{}`", ident.as_str(),))
} else {
(
&before_item.ident.span,
format!("should be placed before `{}`", before_item.ident.as_str(),),
before_item.span,
"should be placed before the following item".to_owned(),
)
};
@ -241,7 +234,7 @@ impl ArbitrarySourceItemOrdering {
return;
}
span_lint_and_note(cx, ARBITRARY_SOURCE_ITEM_ORDERING, *span, msg, Some(*before_span), note);
span_lint_and_note(cx, ARBITRARY_SOURCE_ITEM_ORDERING, span, msg, Some(before_span), note);
}
/// Produces a linting warning for incorrectly ordered trait items.
@ -263,7 +256,7 @@ impl ArbitrarySourceItemOrdering {
impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
match &item.kind {
ItemKind::Enum(enum_def, _generics) if self.enable_ordering_for_enum => {
ItemKind::Enum(_, enum_def, _generics) if self.enable_ordering_for_enum => {
let mut cur_v: Option<&Variant<'_>> = None;
for variant in enum_def.variants {
if variant.span.in_external_macro(cx.sess().source_map()) {
@ -278,7 +271,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
cur_v = Some(variant);
}
},
ItemKind::Struct(VariantData::Struct { fields, .. }, _generics) if self.enable_ordering_for_struct => {
ItemKind::Struct(_, VariantData::Struct { fields, .. }, _generics) if self.enable_ordering_for_struct => {
let mut cur_f: Option<&FieldDef<'_>> = None;
for field in *fields {
if field.span.in_external_macro(cx.sess().source_map()) {
@ -293,7 +286,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
cur_f = Some(field);
}
},
ItemKind::Trait(is_auto, _safety, _generics, _generic_bounds, item_ref)
ItemKind::Trait(is_auto, _safety, _ident, _generics, _generic_bounds, item_ref)
if self.enable_ordering_for_trait && *is_auto == IsAuto::No =>
{
let mut cur_t: Option<&TraitItemRef> = None;
@ -370,50 +363,24 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
continue;
}
// The following exceptions (skipping with `continue;`) may not be
// complete, edge cases have not been explored further than what
// appears in the existing code base.
if item.ident.name == rustc_span::symbol::kw::Empty {
if let ItemKind::Impl(_) = item.kind {
// Sorting trait impls for unnamed types makes no sense.
if get_item_name(item).is_empty() {
continue;
}
} else if let ItemKind::ForeignMod { .. } = item.kind {
continue;
} else if let ItemKind::GlobalAsm { .. } = item.kind {
continue;
} else if let ItemKind::Use(path, use_kind) = item.kind {
if path.segments.is_empty() {
// Use statements that contain braces get caught here.
// They will still be linted internally.
continue;
} else if path.segments.len() >= 2
&& (path.segments[0].ident.name == rustc_span::sym::std
|| path.segments[0].ident.name == rustc_span::sym::core)
&& path.segments[1].ident.name == rustc_span::sym::prelude
{
// Filters the autogenerated prelude use statement.
// e.g. `use std::prelude::rustc_2021`
} else if use_kind == UseKind::Glob {
// Filters glob kinds of uses.
// e.g. `use std::sync::*`
} else {
// This can be used for debugging.
// println!("Unknown autogenerated use statement: {:?}", item);
}
continue;
}
}
let ident = if let Some(ident) = item.kind.ident() {
ident
} else if let ItemKind::Impl(_) = item.kind
&& !get_item_name(item).is_empty()
{
rustc_span::Ident::empty() // FIXME: a bit strange, is there a better way to do it?
} else {
continue;
};
if item.ident.name.as_str().starts_with('_') {
if ident.name.as_str().starts_with('_') {
// Filters out unnamed macro-like impls for various derives,
// e.g. serde::Serialize or num_derive::FromPrimitive.
continue;
}
if item.ident.name == rustc_span::sym::std && item.span.is_dummy() {
if let ItemKind::ExternCrate(None) = item.kind {
if ident.name == rustc_span::sym::std && item.span.is_dummy() {
if let ItemKind::ExternCrate(None, _) = item.kind {
// Filters the auto-included Rust standard library.
continue;
}
@ -559,6 +526,14 @@ fn get_item_name(item: &Item<'_>) -> String {
String::new()
}
},
_ => item.ident.name.as_str().to_owned(),
// FIXME: `Ident::empty` for anonymous items is a bit strange, is there
// a better way to do it?
_ => item
.kind
.ident()
.unwrap_or(rustc_span::Ident::empty())
.name
.as_str()
.to_owned(),
}
}

View file

@ -16,7 +16,7 @@ mod utils;
use clippy_config::Conf;
use clippy_utils::msrvs::{self, Msrv, MsrvStack};
use rustc_ast::{self as ast, Attribute, MetaItemInner, MetaItemKind};
use rustc_hir::{ImplItem, Item, TraitItem};
use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
use rustc_span::sym;
@ -465,22 +465,24 @@ impl Attributes {
impl<'tcx> LateLintPass<'tcx> for Attributes {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
let attrs = cx.tcx.hir().attrs(item.hir_id());
if is_relevant_item(cx, item) {
inline_always::check(cx, item.span, item.ident.name, attrs);
let attrs = cx.tcx.hir_attrs(item.hir_id());
if let ItemKind::Fn { ident, .. } = item.kind
&& is_relevant_item(cx, item)
{
inline_always::check(cx, item.span, ident.name, attrs);
}
repr_attributes::check(cx, item.span, attrs, self.msrv);
}
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
if is_relevant_impl(cx, item) {
inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()));
inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir_attrs(item.hir_id()));
}
}
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
if is_relevant_trait(cx, item) {
inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()));
inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir_attrs(item.hir_id()));
}
}
}

View file

@ -24,7 +24,7 @@ pub(super) fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
if let ItemKind::Fn { body: eid, .. } = item.kind {
is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir_body(eid).value)
} else {
true
false
}
}

View file

@ -97,7 +97,7 @@ fn is_zst<'tcx>(cx: &LateContext<'tcx>, field: &FieldDef, args: ty::GenericArgsR
}
fn has_c_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
let attrs = cx.tcx.hir().attrs(hir_id);
let attrs = cx.tcx.hir_attrs(hir_id);
find_attr!(attrs, AttributeKind::Repr(r) if r.iter().any(|(x, _)| *x == ReprAttr::ReprC))
}

View file

@ -197,9 +197,9 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
&& let ImplItemKind::Fn(_, b) = &impl_item.kind
&& let Body { value: func_expr, .. } = cx.tcx.hir_body(*b)
&& let &ty::Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind()
&& let attrs = cx.tcx.hir().attrs(item.hir_id())
&& let attrs = cx.tcx.hir_attrs(item.hir_id())
&& !attrs.iter().any(|attr| attr.doc_str().is_some())
&& cx.tcx.hir().attrs(impl_item_hir).is_empty()
&& cx.tcx.hir_attrs(impl_item_hir).is_empty()
{
if adt_def.is_struct() {
check_struct(cx, item, self_ty, func_expr, adt_def, args, cx.tcx.typeck_body(*b));

View file

@ -384,7 +384,7 @@ fn check_unsafe_derive_deserialize<'tcx>(
.tcx
.inherent_impls(def.did())
.iter()
.map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local()))
.map(|imp_did| cx.tcx.hir_expect_item(imp_did.expect_local()))
.any(|imp| has_unsafe(cx, imp))
{
span_lint_hir_and_then(

View file

@ -99,7 +99,7 @@ impl_lint_pass!(DisallowedTypes => [DISALLOWED_TYPES]);
impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
if let ItemKind::Use(path, UseKind::Single) = &item.kind {
if let ItemKind::Use(path, UseKind::Single(_)) = &item.kind {
for res in &path.res {
self.check_res_emit(cx, res, item.span);
}

View file

@ -25,7 +25,7 @@ pub fn check(
&& cx
.tcx
.hir_parent_iter(owner_id.into())
.any(|(id, _node)| is_doc_hidden(cx.tcx.hir().attrs(id)))
.any(|(id, _node)| is_doc_hidden(cx.tcx.hir_attrs(id)))
{
return;
}

View file

@ -38,7 +38,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
if cx.tcx.data_layout.pointer_size.bits() != 64 {
return;
}
if let ItemKind::Enum(def, _) = &item.kind {
if let ItemKind::Enum(_, def, _) = &item.kind {
for var in def.variants {
if let Some(anon_const) = &var.disr_expr {
let def_id = cx.tcx.hir_body_owner_def_id(anon_const.body);

View file

@ -37,8 +37,8 @@ declare_lint_pass!(ErrorImplError => [ERROR_IMPL_ERROR]);
impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
match item.kind {
ItemKind::TyAlias(..)
if item.ident.name == sym::Error
ItemKind::TyAlias(ident, ..)
if ident.name == sym::Error
&& is_visible_outside_module(cx, item.owner_id.def_id)
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
&& let Some(error_def_id) = cx.tcx.get_diagnostic_item(sym::Error)
@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
span_lint(
cx,
ERROR_IMPL_ERROR,
item.ident.span,
ident.span,
"exported type alias named `Error` that implements `Error`",
);
},

View file

@ -91,7 +91,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
}
// find `self` ty for this trait if relevant
if let ItemKind::Trait(_, _, _, _, items) = item.kind {
if let ItemKind::Trait(_, _, _, _, _, items) = item.kind {
for trait_item in items {
if trait_item.id.owner_id.def_id == fn_def_id {
// be sure we have `self` parameter in this function
@ -150,6 +150,8 @@ impl<'tcx> Delegate<'tcx> for EscapeDelegate<'_, 'tcx> {
}
}
fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {
if cmt.place.projections.is_empty() {
if let PlaceBase::Local(lid) = cmt.place.base {
@ -160,26 +162,23 @@ impl<'tcx> Delegate<'tcx> for EscapeDelegate<'_, 'tcx> {
}
fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId) {
if cmt.place.projections.is_empty() {
let map = &self.cx.tcx.hir();
if is_argument(self.cx.tcx, cmt.hir_id) {
// Skip closure arguments
let parent_id = self.cx.tcx.parent_hir_id(cmt.hir_id);
if let Node::Expr(..) = self.cx.tcx.parent_hir_node(parent_id) {
if cmt.place.projections.is_empty() && is_argument(self.cx.tcx, cmt.hir_id) {
// Skip closure arguments
let parent_id = self.cx.tcx.parent_hir_id(cmt.hir_id);
if let Node::Expr(..) = self.cx.tcx.parent_hir_node(parent_id) {
return;
}
// skip if there is a `self` parameter binding to a type
// that contains `Self` (i.e.: `self: Box<Self>`), see #4804
if let Some(trait_self_ty) = self.trait_self_ty {
if self.cx.tcx.hir_name(cmt.hir_id) == kw::SelfLower && cmt.place.ty().contains(trait_self_ty) {
return;
}
}
// skip if there is a `self` parameter binding to a type
// that contains `Self` (i.e.: `self: Box<Self>`), see #4804
if let Some(trait_self_ty) = self.trait_self_ty {
if map.name(cmt.hir_id) == kw::SelfLower && cmt.place.ty().contains(trait_self_ty) {
return;
}
}
if is_non_trait_box(cmt.place.ty()) && !self.is_large_box(cmt.place.ty()) {
self.set.insert(cmt.hir_id);
}
if is_non_trait_box(cmt.place.ty()) && !self.is_large_box(cmt.place.ty()) {
self.set.insert(cmt.hir_id);
}
}
}

View file

@ -127,7 +127,7 @@ fn check_fn_decl(cx: &LateContext<'_>, decl: &FnDecl<'_>, sp: Span, max: u64) {
impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
if let ItemKind::Struct(variant_data, _) = &item.kind
if let ItemKind::Struct(_, variant_data, _) = &item.kind
&& variant_data.fields().len() as u64 > self.max_struct_bools
&& has_n_bools(
variant_data.fields().iter().map(|field| field.ty),

View file

@ -76,7 +76,7 @@ impl LateLintPass<'_> for ExhaustiveItems {
"exported enums should not be exhaustive",
[].as_slice(),
),
ItemKind::Struct(v, ..) => (
ItemKind::Struct(_, v, ..) => (
EXHAUSTIVE_STRUCTS,
"exported structs should not be exhaustive",
v.fields(),
@ -84,7 +84,7 @@ impl LateLintPass<'_> for ExhaustiveItems {
_ => return,
};
if cx.effective_visibilities.is_exported(item.owner_id.def_id)
&& let attrs = cx.tcx.hir().attrs(item.hir_id())
&& let attrs = cx.tcx.hir_attrs(item.hir_id())
&& !attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
&& fields.iter().all(|f| cx.tcx.visibility(f.def_id).is_public())
{

View file

@ -209,9 +209,8 @@ impl FormatImplExpr<'_, '_> {
// Handle dereference of &self -> self that is equivalent (i.e. via *self in fmt() impl)
// Since the argument to fmt is itself a reference: &self
let reference = peel_ref_operators(self.cx, arg);
let map = self.cx.tcx.hir();
// Is the reference self?
if path_to_local(reference).map(|x| map.name(x)) == Some(kw::SelfLower) {
if path_to_local(reference).map(|x| self.cx.tcx.hir_name(x)) == Some(kw::SelfLower) {
let FormatTraitNames { name, .. } = self.format_trait_impl;
span_lint(
self.cx,

View file

@ -43,8 +43,7 @@ impl<'tcx> LateLintPass<'tcx> for FourForwardSlashes {
let sm = cx.sess().source_map();
let mut span = cx
.tcx
.hir()
.attrs(item.hir_id())
.hir_attrs(item.hir_id())
.iter()
.filter(|i| i.is_doc_comment())
.fold(item.span.shrink_to_lo(), |span, attr| span.to(attr.span()));

View file

@ -21,7 +21,7 @@ use core::ops::ControlFlow;
use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT};
pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
let attrs = cx.tcx.hir().attrs(item.hir_id());
let attrs = cx.tcx.hir_attrs(item.hir_id());
let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
if let hir::ItemKind::Fn {
ref sig,
@ -51,7 +51,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind {
let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
let attrs = cx.tcx.hir().attrs(item.hir_id());
let attrs = cx.tcx.hir_attrs(item.hir_id());
let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
if let Some(attr) = attr {
check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig);
@ -74,7 +74,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
let attrs = cx.tcx.hir().attrs(item.hir_id());
let attrs = cx.tcx.hir_attrs(item.hir_id());
let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
if let Some(attr) = attr {
check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig);

View file

@ -103,7 +103,7 @@ fn check_result_large_err<'tcx>(cx: &LateContext<'tcx>, err_ty: Ty<'tcx>, hir_ty
.did()
.as_local()
&& let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(local_def_id)
&& let hir::ItemKind::Enum(ref def, _) = item.kind
&& let hir::ItemKind::Enum(_, ref def, _) = item.kind
{
let variants_size = AdtVariantInfo::new(cx, *adt, subst);
if let Some((first_variant, variants)) = variants_size.split_first()

View file

@ -182,7 +182,7 @@ fn suggestion<'tcx>(
}
fn field_with_attrs_span(tcx: TyCtxt<'_>, field: &hir::ExprField<'_>) -> Span {
if let Some(attr) = tcx.hir().attrs(field.hir_id).first() {
if let Some(attr) = tcx.hir_attrs(field.hir_id).first() {
field.span.with_lo(attr.span().lo())
} else {
field.span

View file

@ -32,12 +32,7 @@ declare_lint_pass!(InlineFnWithoutBody => [INLINE_FN_WITHOUT_BODY]);
impl<'tcx> LateLintPass<'tcx> for InlineFnWithoutBody {
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
if let TraitItemKind::Fn(_, TraitFn::Required(_)) = item.kind
&& let Some(attr) = cx
.tcx
.hir()
.attrs(item.hir_id())
.iter()
.find(|a| a.has_name(sym::inline))
&& let Some(attr) = cx.tcx.hir_attrs(item.hir_id()).iter().find(|a| a.has_name(sym::inline))
{
span_lint_and_then(
cx,

View file

@ -206,7 +206,10 @@ impl ItemNameRepetitions {
return;
}
let item_name = item.ident.name.as_str();
let Some(ident) = item.kind.ident() else {
return;
};
let item_name = ident.name.as_str();
for var in def.variants {
check_enum_start(cx, item_name, var);
check_enum_end(cx, item_name, var);
@ -278,7 +281,10 @@ impl ItemNameRepetitions {
fn check_struct_common_affix(&self, cx: &LateContext<'_>, item: &Item<'_>, fields: &[FieldDef<'_>]) {
// if the SyntaxContext of the identifiers of the fields and struct differ dont lint them.
// this prevents linting in macros in which the location of the field identifier names differ
if !fields.iter().all(|field| item.ident.span.eq_ctxt(field.ident.span)) {
if !fields
.iter()
.all(|field| item.kind.ident().is_some_and(|i| i.span.eq_ctxt(field.ident.span)))
{
return;
}
@ -346,14 +352,15 @@ impl ItemNameRepetitions {
}
fn check_struct_name_repetition(&self, cx: &LateContext<'_>, item: &Item<'_>, fields: &[FieldDef<'_>]) {
let snake_name = to_snake_case(item.ident.name.as_str());
let Some(ident) = item.kind.ident() else { return };
let snake_name = to_snake_case(ident.name.as_str());
let item_name_words: Vec<&str> = snake_name.split('_').collect();
for field in fields {
if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(field.def_id) {
continue;
}
if !field.ident.span.eq_ctxt(item.ident.span) {
if !field.ident.span.eq_ctxt(ident.span) {
// consider linting only if the field identifier has the same SyntaxContext as the item(struct)
continue;
}
@ -426,19 +433,23 @@ fn check_enum_end(cx: &LateContext<'_>, item_name: &str, variant: &Variant<'_>)
}
impl LateLintPass<'_> for ItemNameRepetitions {
fn check_item_post(&mut self, _cx: &LateContext<'_>, _item: &Item<'_>) {
fn check_item_post(&mut self, _cx: &LateContext<'_>, item: &Item<'_>) {
let Some(_ident) = item.kind.ident() else { return };
let last = self.modules.pop();
assert!(last.is_some());
}
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
let item_name = item.ident.name.as_str();
let Some(ident) = item.kind.ident() else { return };
let item_name = ident.name.as_str();
let item_camel = to_camel_case(item_name);
if !item.span.from_expansion() && is_present_in_source(cx, item.span) {
if let [.., (mod_name, mod_camel, mod_owner_id)] = &*self.modules {
// constants don't have surrounding modules
if !mod_camel.is_empty() {
if mod_name == &item.ident.name
if mod_name == &ident.name
&& let ItemKind::Mod(..) = item.kind
&& (!self.allow_private_module_inception || cx.tcx.visibility(mod_owner_id.def_id).is_public())
{
@ -467,7 +478,7 @@ impl LateLintPass<'_> for ItemNameRepetitions {
Some(c) if is_word_beginning(c) => span_lint(
cx,
MODULE_NAME_REPETITIONS,
item.ident.span,
ident.span,
"item name starts with its containing module's name",
),
_ => (),
@ -479,7 +490,7 @@ impl LateLintPass<'_> for ItemNameRepetitions {
span_lint(
cx,
MODULE_NAME_REPETITIONS,
item.ident.span,
ident.span,
"item name ends with its containing module's name",
);
}
@ -490,16 +501,15 @@ impl LateLintPass<'_> for ItemNameRepetitions {
if span_is_local(item.span) {
match item.kind {
ItemKind::Enum(def, _) => {
ItemKind::Enum(_, def, _) => {
self.check_variants(cx, item, &def);
},
ItemKind::Struct(VariantData::Struct { fields, .. }, _) => {
ItemKind::Struct(_, VariantData::Struct { fields, .. }, _) => {
self.check_fields(cx, item, fields);
},
_ => (),
}
}
self.modules.push((item.ident.name, item_camel, item.owner_id));
self.modules.push((ident.name, item_camel, item.owner_id));
}
}

View file

@ -44,7 +44,7 @@ declare_clippy_lint! {
declare_lint_pass!(ItemsAfterTestModule => [ITEMS_AFTER_TEST_MODULE]);
fn cfg_test_module<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool {
if let ItemKind::Mod(test_mod) = item.kind
if let ItemKind::Mod(_, test_mod) = item.kind
&& item.span.hi() == test_mod.spans.inner_span.hi()
&& is_cfg_test(cx.tcx, item.hir_id())
&& !item.span.from_expansion()
@ -67,14 +67,20 @@ impl LateLintPass<'_> for ItemsAfterTestModule {
let after: Vec<_> = items
.filter(|item| {
// Ignore the generated test main function
!(item.ident.name == sym::main
&& item.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::TestHarness))
if let ItemKind::Fn { ident, .. } = item.kind
&& ident.name == sym::main
&& item.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::TestHarness)
{
false
} else {
true
}
})
.collect();
if let Some(last) = after.last()
&& after.iter().all(|&item| {
!matches!(item.kind, ItemKind::Mod(_)) && !item.span.from_expansion() && !is_from_proc_macro(cx, item)
!matches!(item.kind, ItemKind::Mod(..)) && !item.span.from_expansion() && !is_from_proc_macro(cx, item)
})
&& !fulfill_or_allowed(cx, ITEMS_AFTER_TEST_MODULE, after.iter().map(|item| item.hir_id()))
{

View file

@ -48,7 +48,7 @@ impl_lint_pass!(LargeConstArrays => [LARGE_CONST_ARRAYS]);
impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if let ItemKind::Const(_, generics, _) = &item.kind
if let ItemKind::Const(ident, _, generics, _) = &item.kind
// Since static items may not have generics, skip generic const items.
// FIXME(generic_const_items): I don't think checking `generics.hwcp` suffices as it
// doesn't account for empty where-clauses that only consist of keyword `where` IINM.
@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
&& let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
&& u128::from(self.maximum_allowed_size) < u128::from(element_count) * u128::from(element_size)
{
let hi_pos = item.ident.span.lo() - BytePos::from_usize(1);
let hi_pos = ident.span.lo() - BytePos::from_usize(1);
let sugg_span = Span::new(
hi_pos - BytePos::from_usize("const".len()),
hi_pos,

View file

@ -73,7 +73,7 @@ impl_lint_pass!(LargeEnumVariant => [LARGE_ENUM_VARIANT]);
impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &Item<'tcx>) {
if let ItemKind::Enum(ref def, _) = item.kind
if let ItemKind::Enum(ident, ref def, _) = item.kind
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
&& let ty::Adt(adt, subst) = ty.kind()
&& adt.variants().len() > 1
@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
let mut applicability = Applicability::MaybeIncorrect;
if is_copy(cx, ty) || maybe_copy(cx, ty) {
diag.span_note(
item.ident.span,
ident.span,
"boxing a variant would require the type no longer be `Copy`",
);
} else {

View file

@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
// Integer modules are "TBD" deprecated, and the contents are too,
// so lint on the `use` statement directly.
if let ItemKind::Use(path, kind @ (UseKind::Single | UseKind::Glob)) = item.kind
if let ItemKind::Use(path, kind @ (UseKind::Single(_) | UseKind::Glob)) = item.kind
&& !item.span.in_external_macro(cx.sess().source_map())
&& let Some(def_id) = path.res[0].opt_def_id()
&& self.msrv.meets(cx, msrvs::NUMERIC_ASSOCIATED_CONSTANTS)
@ -72,7 +72,9 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants {
"importing a legacy numeric constant"
},
|diag| {
if item.ident.name == kw::Underscore {
if let UseKind::Single(ident) = kind
&& ident.name == kw::Underscore
{
diag.help("remove this import");
return;
}

View file

@ -17,7 +17,7 @@ use rustc_middle::ty::{self, AssocKind, FnSig, Ty};
use rustc_session::declare_lint_pass;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol};
use rustc_span::{Ident, Span, Symbol};
use rustc_trait_selection::traits::supertrait_def_ids;
declare_clippy_lint! {
@ -123,10 +123,10 @@ declare_lint_pass!(LenZero => [LEN_ZERO, LEN_WITHOUT_IS_EMPTY, COMPARISON_TO_EMP
impl<'tcx> LateLintPass<'tcx> for LenZero {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if let ItemKind::Trait(_, _, _, _, trait_items) = item.kind
if let ItemKind::Trait(_, _, ident, _, _, trait_items) = item.kind
&& !item.span.from_expansion()
{
check_trait_items(cx, item, trait_items);
check_trait_items(cx, item, ident, trait_items);
}
}
@ -150,10 +150,10 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
let (name, kind) = match cx.tcx.hir_node(ty_hir_id) {
Node::ForeignItem(x) => (x.ident.name, "extern type"),
Node::Item(x) => match x.kind {
ItemKind::Struct(..) => (x.ident.name, "struct"),
ItemKind::Enum(..) => (x.ident.name, "enum"),
ItemKind::Union(..) => (x.ident.name, "union"),
_ => (x.ident.name, "type"),
ItemKind::Struct(ident, ..) => (ident.name, "struct"),
ItemKind::Enum(ident, ..) => (ident.name, "enum"),
ItemKind::Union(ident, ..) => (ident.name, "union"),
_ => (x.kind.ident().unwrap().name, "type"),
},
_ => return,
};
@ -250,7 +250,7 @@ fn span_without_enclosing_paren(cx: &LateContext<'_>, span: Span) -> Span {
}
}
fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items: &[TraitItemRef]) {
fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, ident: Ident, trait_items: &[TraitItemRef]) {
fn is_named_self(cx: &LateContext<'_>, item: &TraitItemRef, name: Symbol) -> bool {
item.ident.name == name
&& if let AssocItemKind::Fn { has_self } = item.kind {
@ -300,7 +300,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items
visited_trait.span,
format!(
"trait `{}` has a `len` method but no (possibly inherited) `is_empty` method",
visited_trait.ident.name
ident.name
),
);
}

View file

@ -79,6 +79,8 @@ struct MutatePairDelegate<'a, 'tcx> {
impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) {
if bk == ty::BorrowKind::Mutable {
if let PlaceBase::Local(id) = cmt.place.base {
@ -127,7 +129,7 @@ impl BreakAfterExprVisitor {
};
get_enclosing_block(cx, hir_id).is_some_and(|block| {
visitor.visit_block(block);
let _ = visitor.visit_block(block);
visitor.break_after_expr
})
}

View file

@ -177,6 +177,7 @@ fn never_loop_expr<'tcx>(
| ExprKind::UnsafeBinderCast(_, e, _) => never_loop_expr(cx, e, local_labels, main_loop_id),
ExprKind::Let(let_expr) => never_loop_expr(cx, let_expr.init, local_labels, main_loop_id),
ExprKind::Array(es) | ExprKind::Tup(es) => never_loop_expr_all(cx, es.iter(), local_labels, main_loop_id),
ExprKind::Use(expr, _) => never_loop_expr(cx, expr, local_labels, main_loop_id),
ExprKind::MethodCall(_, receiver, es, _) => {
never_loop_expr_all(cx, once(receiver).chain(es.iter()), local_labels, main_loop_id)
},

View file

@ -98,7 +98,7 @@ impl LateLintPass<'_> for MacroUseImports {
if cx.sess().opts.edition >= Edition::Edition2018
&& let hir::ItemKind::Use(path, _kind) = &item.kind
&& let hir_id = item.hir_id()
&& let attrs = cx.tcx.hir().attrs(hir_id)
&& let attrs = cx.tcx.hir_attrs(hir_id)
&& let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use))
&& let Some(id) = path.res.iter().find_map(|res| match res {
Res::Def(DefKind::Mod, id) => Some(id),

View file

@ -87,18 +87,18 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
}
match item.kind {
ItemKind::Enum(def, _) if def.variants.len() > 1 => {
ItemKind::Enum(_, def, _) if def.variants.len() > 1 => {
let iter = def.variants.iter().filter_map(|v| {
(matches!(v.data, VariantData::Unit(_, _)) && is_doc_hidden(cx.tcx.hir().attrs(v.hir_id)))
(matches!(v.data, VariantData::Unit(_, _)) && is_doc_hidden(cx.tcx.hir_attrs(v.hir_id)))
.then_some((v.def_id, v.span))
});
if let Ok((id, span)) = iter.exactly_one()
&& !attr::contains_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive)
&& !attr::contains_name(cx.tcx.hir_attrs(item.hir_id()), sym::non_exhaustive)
{
self.potential_enums.push((item.owner_id.def_id, id, item.span, span));
}
},
ItemKind::Struct(variant_data, _) => {
ItemKind::Struct(_, variant_data, _) => {
let fields = variant_data.fields();
let private_fields = fields
.iter()
@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
"this seems like a manual implementation of the non-exhaustive pattern",
|diag| {
if let Some(non_exhaustive) =
attr::find_by_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive)
attr::find_by_name(cx.tcx.hir_attrs(item.hir_id()), sym::non_exhaustive)
{
diag.span_note(non_exhaustive.span(), "the struct is already non-exhaustive");
} else {

View file

@ -99,7 +99,7 @@ where
});
if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(l), .. })) = e.kind {
match captures.get(l) {
Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None,
Some(CaptureKind::Value | CaptureKind::Use | CaptureKind::Ref(Mutability::Mut)) => return None,
Some(CaptureKind::Ref(Mutability::Not)) if binding_ref_mutability == Mutability::Mut => {
return None;
},

View file

@ -42,7 +42,7 @@ pub(super) fn check_match<'tcx>(
cx,
scrutinee,
arms.iter()
.map(|arm| (cx.tcx.hir().attrs(arm.hir_id), Some(arm.pat), arm.body, arm.guard)),
.map(|arm| (cx.tcx.hir_attrs(arm.hir_id), Some(arm.pat), arm.body, arm.guard)),
e,
false,
)

View file

@ -75,7 +75,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
HirIdMapEntry::Occupied(entry) => return *entry.get() == b_id,
}
// the names technically don't have to match; this makes the lint more conservative
&& cx.tcx.hir().name(a_id) == cx.tcx.hir().name(b_id)
&& cx.tcx.hir_name(a_id) == cx.tcx.hir_name(b_id)
&& cx.typeck_results().expr_ty(a) == cx.typeck_results().expr_ty(b)
&& pat_contains_local(lhs.pat, a_id)
&& pat_contains_local(rhs.pat, b_id)

View file

@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_
fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool {
cx.tcx
.hir_parent_id_iter(id)
.any(|id| cx.tcx.hir().attrs(id).iter().any(|attr| attr.has_name(sym::cfg)))
.any(|id| cx.tcx.hir_attrs(id).iter().any(|attr| attr.has_name(sym::cfg)))
}
/// Similar to [`clippy_utils::expr_or_init`], but does not go up the chain if the initialization

View file

@ -147,6 +147,8 @@ impl<'tcx> Delegate<'tcx> for MoveDelegate {
}
}
fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
fn borrow(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId, _: BorrowKind) {}
fn mutate(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}

View file

@ -4731,7 +4731,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
}
let name = impl_item.ident.name.as_str();
let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
let item = cx.tcx.hir().expect_item(parent);
let item = cx.tcx.hir_expect_item(parent);
let self_ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
let implements_trait = matches!(item.kind, hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }));

View file

@ -40,7 +40,7 @@ pub fn check(cx: &LateContext<'_>, call: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<
// We've checked that `call` is a call to `Stdin::read_line()` with the right receiver,
// now let's check if the first use of the string passed to `::read_line()`
// is used for operations that will always fail (e.g. parsing "6\n" into a number)
for_each_local_use_after_expr(cx, local_id, call.hir_id, |expr| {
let _ = for_each_local_use_after_expr(cx, local_id, call.hir_id, |expr| {
if let Some(parent) = get_parent_expr(cx, expr) {
let data = if let ExprKind::MethodCall(segment, recv, args, span) = parent.kind {
if args.is_empty()

View file

@ -182,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
}
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID);
let attrs = cx.tcx.hir_attrs(hir::CRATE_HIR_ID);
self.check_missing_docs_attrs(cx, CRATE_DEF_ID, attrs, cx.tcx.def_span(CRATE_DEF_ID), "the", "crate");
}
@ -192,17 +192,17 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) {
match it.kind {
hir::ItemKind::Fn { .. } => {
hir::ItemKind::Fn { ident, .. } => {
// ignore main()
if it.ident.name == sym::main {
if ident.name == sym::main {
let at_root = cx.tcx.local_parent(it.owner_id.def_id) == CRATE_DEF_ID;
if at_root {
note_prev_span_then_ret!(self.prev_span, it.span);
}
}
},
hir::ItemKind::Const(..) => {
if it.ident.name == kw::Underscore {
hir::ItemKind::Const(ident, ..) => {
if ident.name == kw::Underscore {
note_prev_span_then_ret!(self.prev_span, it.span);
}
},
@ -224,7 +224,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
let (article, desc) = cx.tcx.article_and_description(it.owner_id.to_def_id());
let attrs = cx.tcx.hir().attrs(it.hir_id());
let attrs = cx.tcx.hir_attrs(it.hir_id());
if !is_from_proc_macro(cx, it) {
self.check_missing_docs_attrs(cx, it.owner_id.def_id, attrs, it.span, article, desc);
}
@ -234,7 +234,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx hir::TraitItem<'_>) {
let (article, desc) = cx.tcx.article_and_description(trait_item.owner_id.to_def_id());
let attrs = cx.tcx.hir().attrs(trait_item.hir_id());
let attrs = cx.tcx.hir_attrs(trait_item.hir_id());
if !is_from_proc_macro(cx, trait_item) {
self.check_missing_docs_attrs(cx, trait_item.owner_id.def_id, attrs, trait_item.span, article, desc);
}
@ -252,7 +252,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
}
let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id());
let attrs = cx.tcx.hir().attrs(impl_item.hir_id());
let attrs = cx.tcx.hir_attrs(impl_item.hir_id());
if !is_from_proc_macro(cx, impl_item) {
self.check_missing_docs_attrs(cx, impl_item.owner_id.def_id, attrs, impl_item.span, article, desc);
}
@ -261,7 +261,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
fn check_field_def(&mut self, cx: &LateContext<'tcx>, sf: &'tcx hir::FieldDef<'_>) {
if !sf.is_positional() {
let attrs = cx.tcx.hir().attrs(sf.hir_id);
let attrs = cx.tcx.hir_attrs(sf.hir_id);
if !is_from_proc_macro(cx, sf) {
self.check_missing_docs_attrs(cx, sf.def_id, attrs, sf.span, "a", "struct field");
}
@ -270,7 +270,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
}
fn check_variant(&mut self, cx: &LateContext<'tcx>, v: &'tcx hir::Variant<'_>) {
let attrs = cx.tcx.hir().attrs(v.hir_id);
let attrs = cx.tcx.hir_attrs(v.hir_id);
if !is_from_proc_macro(cx, v) {
self.check_missing_docs_attrs(cx, v.def_id, attrs, v.span, "a", "variant");
}

View file

@ -67,7 +67,7 @@ impl_lint_pass!(ImportRename => [MISSING_ENFORCED_IMPORT_RENAMES]);
impl LateLintPass<'_> for ImportRename {
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
if let ItemKind::Use(path, UseKind::Single) = &item.kind {
if let ItemKind::Use(path, UseKind::Single(_)) = &item.kind {
for &res in &path.res {
if let Res::Def(_, id) = res
&& let Some(name) = self.renames.get(&id)

View file

@ -226,7 +226,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug {
&& should_lint(cx, typeck_results, block)
{
// we intentionally only lint structs, see lint description
if let ItemKind::Struct(data, _) = &self_item.kind {
if let ItemKind::Struct(_, data, _) = &self_item.kind {
check_struct(cx, typeck_results, block, self_ty, item, data);
}
}

View file

@ -98,10 +98,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
match it.kind {
hir::ItemKind::Fn { .. } => {
let desc = "a function";
let attrs = cx.tcx.hir().attrs(it.hir_id());
let attrs = cx.tcx.hir_attrs(it.hir_id());
check_missing_inline_attrs(cx, attrs, it.span, desc);
},
hir::ItemKind::Trait(ref _is_auto, ref _unsafe, _generics, _bounds, trait_items) => {
hir::ItemKind::Trait(ref _is_auto, ref _unsafe, _ident, _generics, _bounds, trait_items) => {
// note: we need to check if the trait is exported so we can't use
// `LateLintPass::check_trait_item` here.
for tit in trait_items {
@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
// an impl is not provided
let desc = "a default trait method";
let item = cx.tcx.hir_trait_item(tit.id);
let attrs = cx.tcx.hir().attrs(item.hir_id());
let attrs = cx.tcx.hir_attrs(item.hir_id());
check_missing_inline_attrs(cx, attrs, item.span, desc);
}
},
@ -168,7 +168,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
}
}
let attrs = cx.tcx.hir().attrs(impl_item.hir_id());
let attrs = cx.tcx.hir_attrs(impl_item.hir_id());
check_missing_inline_attrs(cx, attrs, impl_item.span, desc);
}
}

View file

@ -334,7 +334,7 @@ impl<'tcx> Visitor<'tcx> for ReadVisitor<'_, 'tcx> {
self.cx,
MIXED_READ_WRITE_IN_EXPRESSION,
expr.span,
format!("unsequenced read of `{}`", self.cx.tcx.hir().name(self.var)),
format!("unsequenced read of `{}`", self.cx.tcx.hir_name(self.var)),
|diag| {
diag.span_note(
self.write_expr.span,

View file

@ -65,7 +65,7 @@ impl LateLintPass<'_> for NeedlessIf {
stmt.span,
"this `if` branch is empty",
"you can remove it",
if cond.can_have_side_effects() || !cx.tcx.hir().attrs(stmt.hir_id).is_empty() {
if cond.can_have_side_effects() || !cx.tcx.hir_attrs(stmt.hir_id).is_empty() {
// `{ foo }` or `{ foo } && bar` placed into a statement position would be
// interpreted as a block statement, force it to be an expression
if cond_snippet.starts_with('{') {

View file

@ -259,7 +259,7 @@ fn check<'tcx>(
binding_id: HirId,
) -> Option<()> {
let usage = first_usage(cx, binding_id, local_stmt.hir_id, block)?;
let binding_name = cx.tcx.hir().opt_name(binding_id)?;
let binding_name = cx.tcx.hir_opt_name(binding_id)?;
let let_snippet = local_snippet_without_semicolon(cx, local)?;
match usage.expr.kind {

View file

@ -147,7 +147,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
// We don't check unsafe functions.
return;
}
let attrs = cx.tcx.hir().attrs(hir_id);
let attrs = cx.tcx.hir_attrs(hir_id);
if header.abi != ExternAbi::Rust || requires_exact_signature(attrs) {
return;
}
@ -396,6 +396,8 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
}
}
fn use_cloned(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId) {}
#[allow(clippy::if_same_then_else)]
fn borrow(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, id: HirId, borrow: ty::BorrowKind) {
self.prev_bind = None;

View file

@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
match kind {
FnKind::ItemFn(.., header) => {
let attrs = cx.tcx.hir().attrs(hir_id);
let attrs = cx.tcx.hir_attrs(hir_id);
if header.abi != ExternAbi::Rust || requires_exact_signature(attrs) {
return;
}
@ -326,6 +326,8 @@ impl<'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt {
self.move_common(cmt);
}
fn use_cloned(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId) {}
fn borrow(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {}
fn mutate(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId) {}

View file

@ -37,12 +37,12 @@ declare_lint_pass!(NoMangleWithRustAbi => [NO_MANGLE_WITH_RUST_ABI]);
impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
if let ItemKind::Fn { sig: fn_sig, .. } = &item.kind
if let ItemKind::Fn { ident, sig: fn_sig, .. } = &item.kind
&& !item.span.from_expansion()
{
let attrs = cx.tcx.hir().attrs(item.hir_id());
let attrs = cx.tcx.hir_attrs(item.hir_id());
let mut app = Applicability::MaybeIncorrect;
let fn_snippet = snippet_with_applicability(cx, fn_sig.span.with_hi(item.ident.span.lo()), "..", &mut app);
let fn_snippet = snippet_with_applicability(cx, fn_sig.span.with_hi(ident.span.lo()), "..", &mut app);
for attr in attrs {
if let Some(ident) = attr.ident()
&& ident.name == rustc_span::sym::no_mangle

View file

@ -351,7 +351,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
if let ImplItemKind::Const(_, body_id) = &impl_item.kind {
let item_def_id = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
let item = cx.tcx.hir().expect_item(item_def_id);
let item = cx.tcx.hir_expect_item(item_def_id);
match &item.kind {
ItemKind::Impl(Impl {

View file

@ -192,7 +192,7 @@ struct LazyInfo {
impl LazyInfo {
fn from_item(state: &NonStdLazyStatic, cx: &LateContext<'_>, item: &Item<'_>) -> Option<Self> {
// Check if item is a `once_cell:sync::Lazy` static.
if let ItemKind::Static(ty, _, body_id) = item.kind
if let ItemKind::Static(_, ty, _, body_id) = item.kind
&& let Some(path_def_id) = path_def_id(cx, ty)
&& let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
&& state.once_cell_sync_lazy.contains(&path_def_id)

View file

@ -112,6 +112,7 @@ fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet {
}
fn consume(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
fn use_cloned(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: HirId) {}
fn copy(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
@ -137,6 +138,7 @@ fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet {
}
fn consume(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
fn use_cloned(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
fn mutate(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}
fn fake_read(&mut self, _: &PlaceWithHirId<'_>, _: FakeReadCause, _: HirId) {}
fn copy(&mut self, _: &PlaceWithHirId<'_>, _: HirId) {}

View file

@ -50,7 +50,7 @@ pub(crate) fn check<'tcx>(
// format the suggestion
let suggestion = format!(
"{}.abs()",
sugg::make_assoc(AssocOp::Subtract, &sug_l, &sug_r).maybe_par()
sugg::make_assoc(AssocOp::Binary(BinOpKind::Sub), &sug_l, &sug_r).maybe_par()
);
// spans the lint
span_lint_and_then(

View file

@ -181,7 +181,7 @@ fn in_impl<'tcx>(
) -> Option<(&'tcx rustc_hir::Ty<'tcx>, &'tcx rustc_hir::Ty<'tcx>)> {
if let Some(block) = get_enclosing_block(cx, e.hir_id)
&& let Some(impl_def_id) = cx.tcx.impl_of_method(block.hir_id.owner.to_def_id())
&& let item = cx.tcx.hir().expect_item(impl_def_id.expect_local())
&& let item = cx.tcx.hir_expect_item(impl_def_id.expect_local())
&& let ItemKind::Impl(item) = &item.kind
&& let Some(of_trait) = &item.of_trait
&& let Some(seg) = of_trait.path.segments.last()
@ -200,7 +200,7 @@ fn in_impl<'tcx>(
fn are_equal(cx: &LateContext<'_>, middle_ty: Ty<'_>, hir_ty: &rustc_hir::Ty<'_>) -> bool {
if let ty::Adt(adt_def, _) = middle_ty.kind()
&& let Some(local_did) = adt_def.did().as_local()
&& let item = cx.tcx.hir().expect_item(local_did)
&& let item = cx.tcx.hir_expect_item(local_did)
&& let middle_ty_id = item.owner_id.to_def_id()
&& let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind
&& let Res::Def(_, hir_ty_id) = path.res

View file

@ -185,7 +185,7 @@ fn try_get_option_occurrence<'tcx>(
.then_some(())
.and_then(|()| none_captures.get(local_id))
}) {
Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None,
Some(CaptureKind::Value | CaptureKind::Use | CaptureKind::Ref(Mutability::Mut)) => return None,
Some(CaptureKind::Ref(Mutability::Not)) if as_mut => return None,
Some(CaptureKind::Ref(Mutability::Not)) | None => (),
}

View file

@ -141,7 +141,7 @@ impl PassByRefOrValue {
// Gather all the lifetimes found in the output type which may affect whether
// `TRIVIALLY_COPY_PASS_BY_REF` should be linted.
let mut output_regions = FxHashSet::default();
for_each_top_level_late_bound_region(fn_sig.skip_binder().output(), |region| -> ControlFlow<!> {
let _ = for_each_top_level_late_bound_region(fn_sig.skip_binder().output(), |region| -> ControlFlow<!> {
output_regions.insert(region);
ControlFlow::Continue(())
});
@ -280,7 +280,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
if header.abi != ExternAbi::Rust {
return;
}
let attrs = cx.tcx.hir().attrs(hir_id);
let attrs = cx.tcx.hir_attrs(hir_id);
for a in attrs {
if let Some(meta_items) = a.meta_item_list() {
if a.has_name(sym::proc_macro_derive)

View file

@ -58,7 +58,7 @@ impl PubUnderscoreFields {
impl<'tcx> LateLintPass<'tcx> for PubUnderscoreFields {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
// This lint only pertains to structs.
let ItemKind::Struct(variant_data, _) = &item.kind else {
let ItemKind::Struct(_, variant_data, _) = &item.kind else {
return;
};
@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for PubUnderscoreFields {
// Only pertains to fields that start with an underscore, and are public.
if field.ident.as_str().starts_with('_') && is_visible(field)
// We ignore fields that have `#[doc(hidden)]`.
&& !is_doc_hidden(cx.tcx.hir().attrs(field.hir_id))
&& !is_doc_hidden(cx.tcx.hir_attrs(field.hir_id))
// We ignore fields that are `PhantomData`.
&& !is_path_lang_item(cx, field.ty, LangItem::PhantomData)
{

View file

@ -93,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec {
},
),
VecInitKind::WithExprCapacity(hir_id) => {
let e = cx.tcx.hir().expect_expr(hir_id);
let e = cx.tcx.hir_expect_expr(hir_id);
span_lint_hir_and_then(
cx,
READ_ZERO_BYTE_VEC,

View file

@ -52,7 +52,13 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
&& is_not_macro_export(item)
&& !item.span.in_external_macro(cx.sess().source_map())
{
let span = item.span.with_hi(item.ident.span.hi());
// FIXME: `DUMMY_SP` isn't right here, because it causes the
// resulting span to begin at the start of the file.
let span = item.span.with_hi(
item.kind
.ident()
.map_or(rustc_span::DUMMY_SP.hi(), |ident| ident.span.hi()),
);
let descr = cx.tcx.def_kind(item.owner_id).descr(item.owner_id.to_def_id());
span_lint_and_then(
cx,

View file

@ -74,7 +74,7 @@ fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, spa
// We only show this warning for public exported methods.
&& cx.effective_visibilities.is_exported(fn_def)
// We don't want to emit this lint if the `#[must_use]` attribute is already there.
&& !cx.tcx.hir().attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use))
&& !cx.tcx.hir_attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use))
&& cx.tcx.visibility(fn_def.to_def_id()).is_public()
&& let ret_ty = return_ty(cx, owner_id)
&& let self_arg = nth_arg(cx, owner_id, 0)

View file

@ -231,7 +231,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
&& let Some(stmt) = block.stmts.iter().last()
&& let StmtKind::Let(local) = &stmt.kind
&& local.ty.is_none()
&& cx.tcx.hir().attrs(local.hir_id).is_empty()
&& cx.tcx.hir_attrs(local.hir_id).is_empty()
&& let Some(initexpr) = &local.init
&& let PatKind::Binding(_, local_id, _, _) = local.pat.kind
&& path_to_local_id(retexpr, local_id)
@ -401,7 +401,7 @@ fn check_final_expr<'tcx>(
// This allows the addition of attributes, like `#[allow]` (See: clippy#9361)
// `#[expect(clippy::needless_return)]` needs to be handled separately to
// actually fulfill the expectation (clippy::#12998)
match cx.tcx.hir().attrs(expr.hir_id) {
match cx.tcx.hir_attrs(expr.hir_id) {
[] => {},
[attr] => {
if matches!(Level::from_attr(attr), Some(Level::Expect(_)))

View file

@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors {
}
let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
let item = cx.tcx.hir().expect_item(parent);
let item = cx.tcx.hir_expect_item(parent);
let self_ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
let ret_ty = return_ty(cx, impl_item.owner_id);
@ -73,7 +73,8 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors {
if let Some(self_def) = self_ty.ty_adt_def()
&& let Some(self_local_did) = self_def.did().as_local()
&& let Node::Item(x) = cx.tcx.hir_node_by_def_id(self_local_did)
&& let type_name = x.ident.name.as_str().to_lowercase()
&& let Some(type_ident) = x.kind.ident()
&& let type_name = type_ident.name.as_str().to_lowercase()
&& (impl_item.ident.name.as_str() == type_name
|| impl_item.ident.name.as_str().replace('_', "") == type_name)
{

View file

@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray {
}
fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool {
if let ItemKind::Struct(data, _) = &item.kind
if let ItemKind::Struct(_, data, _) = &item.kind
&& let Some(last_field) = data.fields().last()
&& let field_ty = cx.tcx.normalize_erasing_regions(
cx.typing_env(),

View file

@ -112,7 +112,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
// special handling for self trait bounds as these are not considered generics
// ie. trait Foo: Display {}
if let Item {
kind: ItemKind::Trait(_, _, _, bounds, ..),
kind: ItemKind::Trait(_, _, _, _, bounds, ..),
..
} = item
{
@ -133,7 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
..
}) = segments.first()
&& let Some(Node::Item(Item {
kind: ItemKind::Trait(_, _, _, self_bounds, _),
kind: ItemKind::Trait(_, _, _, _, self_bounds, _),
..
})) = cx.tcx.hir_get_if_local(*def_id)
{

View file

@ -447,7 +447,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id);
match item.kind {
ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _, _) => self.check_ty(
ItemKind::Static(_, ty, _, _) | ItemKind::Const(_, ty, _, _) => self.check_ty(
cx,
ty,
CheckTyContext {

View file

@ -381,7 +381,7 @@ impl UnconditionalRecursion {
implemented_ty_id,
method_span,
};
walk_body(&mut c, body);
let _ = walk_body(&mut c, body);
}
}
}

View file

@ -460,7 +460,7 @@ fn block_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
}
fn include_attrs_in_span(cx: &LateContext<'_>, hir_id: HirId, span: Span) -> Span {
span.to(cx.tcx.hir().attrs(hir_id).iter().fold(span, |acc, attr| {
span.to(cx.tcx.hir_attrs(hir_id).iter().fold(span, |acc, attr| {
if attr.is_doc_comment() {
return acc;
}
@ -488,7 +488,7 @@ fn item_has_safety_comment(cx: &LateContext<'_>, item: &hir::Item<'_>) -> HasSaf
let comment_start = match cx.tcx.parent_hir_node(item.hir_id()) {
Node::Crate(parent_mod) => comment_start_before_item_in_mod(cx, parent_mod, parent_mod.spans.inner_span, item),
Node::Item(parent_item) => {
if let ItemKind::Mod(parent_mod) = &parent_item.kind {
if let ItemKind::Mod(_, parent_mod) = &parent_item.kind {
comment_start_before_item_in_mod(cx, parent_mod, parent_item.span, item)
} else {
// Doesn't support impls in this position. Pretend a comment was found.
@ -643,7 +643,7 @@ fn get_body_search_span(cx: &LateContext<'_>) -> Option<Span> {
match parent_node {
Node::Crate(mod_) => return Some(mod_.spans.inner_span),
Node::Item(hir::Item {
kind: ItemKind::Mod(mod_),
kind: ItemKind::Mod(_, mod_),
span,
..
}) => {

View file

@ -130,9 +130,9 @@ impl LateLintPass<'_> for UnnecessaryBoxReturns {
}
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
let ItemKind::Fn { sig, .. } = &item.kind else {
let ItemKind::Fn { ident, sig, .. } = &item.kind else {
return;
};
self.check_fn_item(cx, sig.decl, item.owner_id.def_id, item.ident.name);
self.check_fn_item(cx, sig.decl, item.owner_id.def_id, ident.name);
}
}

View file

@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
return;
}
let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
let parent_item = cx.tcx.hir().expect_item(parent);
let parent_item = cx.tcx.hir_expect_item(parent);
let assoc_item = cx.tcx.associated_item(impl_item.owner_id);
let contains_todo = |cx, body: &'_ Body<'_>| -> bool {
clippy_utils::visitors::for_each_expr_without_closures(body.value, |e| {

View file

@ -60,9 +60,9 @@ impl_lint_pass!(UnusedTraitNames => [UNUSED_TRAIT_NAMES]);
impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
if !item.span.in_external_macro(cx.sess().source_map())
&& let ItemKind::Use(path, UseKind::Single) = item.kind
&& let ItemKind::Use(path, UseKind::Single(ident)) = item.kind
// Ignore imports that already use Underscore
&& item.ident.name != kw::Underscore
&& ident.name != kw::Underscore
// Only check traits
&& let Some(Res::Def(DefKind::Trait, _)) = path.res.first()
&& cx.tcx.maybe_unused_trait_imports(()).contains(&item.owner_id.def_id)
@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames {
&& self.msrv.meets(cx, msrvs::UNDERSCORE_IMPORTS)
&& !is_from_proc_macro(cx, &last_segment.ident)
{
let complete_span = last_segment.ident.span.to(item.ident.span);
let complete_span = last_segment.ident.span.to(ident.span);
span_lint_and_sugg(
cx,
UNUSED_TRAIT_NAMES,

View file

@ -230,6 +230,8 @@ impl<'tcx> Delegate<'tcx> for MutationVisitor<'tcx> {
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
}
@ -316,7 +318,7 @@ impl<'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'_, 'tcx> {
{
if call_to_unwrap == unwrappable.safe_to_unwrap {
let is_entire_condition = unwrappable.is_entire_condition;
let unwrappable_variable_name = self.cx.tcx.hir().name(unwrappable.local_id);
let unwrappable_variable_name = self.cx.tcx.hir_name(unwrappable.local_id);
let suggested_pattern = if call_to_unwrap {
unwrappable.kind.success_variant_pattern()
} else {

View file

@ -131,11 +131,11 @@ impl LateLintPass<'_> for UpperCaseAcronyms {
return;
}
match it.kind {
ItemKind::TyAlias(..) | ItemKind::Struct(..) | ItemKind::Trait(..) => {
check_ident(cx, &it.ident, it.hir_id(), self.upper_case_acronyms_aggressive);
ItemKind::TyAlias(ident, ..) | ItemKind::Struct(ident, ..) | ItemKind::Trait(_, _, ident, ..) => {
check_ident(cx, &ident, it.hir_id(), self.upper_case_acronyms_aggressive);
},
ItemKind::Enum(ref enumdef, _) => {
check_ident(cx, &it.ident, it.hir_id(), self.upper_case_acronyms_aggressive);
ItemKind::Enum(ident, ref enumdef, _) => {
check_ident(cx, &ident, it.hir_id(), self.upper_case_acronyms_aggressive);
// check enum variants separately because again we only want to lint on private enums and
// the fn check_variant does not know about the vis of the enum of its variants
enumdef.variants.iter().for_each(|variant| {

View file

@ -426,6 +426,11 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
kind!("Tup({elements})");
self.slice(elements, |e| self.expr(e));
},
ExprKind::Use(expr, _) => {
bind!(self, expr);
kind!("Use({expr})");
self.expr(expr);
},
ExprKind::Binary(op, left, right) => {
bind!(self, op, left, right);
kind!("Binary({op}, {left}, {right})");
@ -488,6 +493,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
}) => {
let capture_clause = match capture_clause {
CaptureBy::Value { .. } => "Value { .. }",
CaptureBy::Use { .. } => "Use { .. }",
CaptureBy::Ref => "Ref",
};
@ -787,7 +793,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
}
fn has_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
let attrs = cx.tcx.hir().attrs(hir_id);
let attrs = cx.tcx.hir_attrs(hir_id);
get_attr(cx.sess(), attrs, "author").count() > 0
}

View file

@ -59,6 +59,6 @@ impl<'tcx> LateLintPass<'tcx> for DumpHir {
}
fn has_attr(cx: &LateContext<'_>, hir_id: hir::HirId) -> bool {
let attrs = cx.tcx.hir().attrs(hir_id);
let attrs = cx.tcx.hir_attrs(hir_id);
get_attr(cx.sess(), attrs, "dump").count() > 0
}

View file

@ -44,11 +44,10 @@ impl AlmostStandardFormulation {
impl<'tcx> LateLintPass<'tcx> for AlmostStandardFormulation {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
let mut check_next = false;
if let ItemKind::Static(ty, Mutability::Not, _) = item.kind {
if let ItemKind::Static(_, ty, Mutability::Not, _) = item.kind {
let lines = cx
.tcx
.hir()
.attrs(item.hir_id())
.hir_attrs(item.hir_id())
.iter()
.filter_map(|attr| Attribute::doc_str(attr).map(|sym| (sym, attr)));
if is_lint_ref_type(cx, ty) {

View file

@ -104,7 +104,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
return;
}
if let hir::ItemKind::Static(ty, Mutability::Not, body_id) = item.kind {
if let hir::ItemKind::Static(ident, ty, Mutability::Not, body_id) = item.kind {
if is_lint_ref_type(cx, ty) {
check_invalid_clippy_version_attribute(cx, item);
@ -133,10 +133,10 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
cx,
DEFAULT_LINT,
item.span,
format!("the lint `{}` has the default lint description", item.ident.name),
format!("the lint `{}` has the default lint description", ident.name),
);
}
self.declared_lints.insert(item.ident.name, item.span);
self.declared_lints.insert(ident.name, item.span);
}
}
} else if let Some(macro_call) = root_macro_call_first_node(cx, item) {
@ -247,7 +247,7 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<'
/// This function extracts the version value of a `clippy::version` attribute if the given value has
/// one
pub(super) fn extract_clippy_version_value(cx: &LateContext<'_>, item: &'_ Item<'_>) -> Option<Symbol> {
let attrs = cx.tcx.hir().attrs(item.hir_id());
let attrs = cx.tcx.hir_attrs(item.hir_id());
attrs.iter().find_map(|attr| {
if let hir::Attribute::Unparsed(attr_kind) = &attr
// Identify attribute

View file

@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain:
<!-- begin autogenerated nightly -->
```
nightly-2025-02-27
nightly-2025-03-20
```
<!-- end autogenerated nightly -->

View file

@ -364,6 +364,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
generics: lg,
contract: lc,
body: lb,
define_opaque: _,
}),
Fn(box ast::Fn {
defaultness: rd,
@ -371,6 +372,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
generics: rg,
contract: rc,
body: rb,
define_opaque: _,
}),
) => {
eq_defaultness(*ld, *rd)
@ -502,6 +504,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
generics: lg,
contract: lc,
body: lb,
define_opaque: _,
}),
Fn(box ast::Fn {
defaultness: rd,
@ -509,6 +512,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
generics: rg,
contract: rc,
body: rb,
define_opaque: _,
}),
) => {
eq_defaultness(*ld, *rd)
@ -567,6 +571,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
generics: lg,
contract: lc,
body: lb,
define_opaque: _,
}),
Fn(box ast::Fn {
defaultness: rd,
@ -574,6 +579,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
generics: rg,
contract: rc,
body: rb,
define_opaque: _,
}),
) => {
eq_defaultness(*ld, *rd)
@ -682,19 +688,20 @@ pub fn eq_generics(l: &Generics, r: &Generics) -> bool {
pub fn eq_where_predicate(l: &WherePredicate, r: &WherePredicate) -> bool {
use WherePredicateKind::*;
match (&l.kind, &r.kind) {
(BoundPredicate(l), BoundPredicate(r)) => {
over(&l.bound_generic_params, &r.bound_generic_params, |l, r| {
eq_generic_param(l, r)
}) && eq_ty(&l.bounded_ty, &r.bounded_ty)
&& over(&l.bounds, &r.bounds, eq_generic_bound)
},
(RegionPredicate(l), RegionPredicate(r)) => {
eq_id(l.lifetime.ident, r.lifetime.ident) && over(&l.bounds, &r.bounds, eq_generic_bound)
},
(EqPredicate(l), EqPredicate(r)) => eq_ty(&l.lhs_ty, &r.lhs_ty) && eq_ty(&l.rhs_ty, &r.rhs_ty),
_ => false,
}
over(&l.attrs, &r.attrs, eq_attr)
&& match (&l.kind, &r.kind) {
(BoundPredicate(l), BoundPredicate(r)) => {
over(&l.bound_generic_params, &r.bound_generic_params, |l, r| {
eq_generic_param(l, r)
}) && eq_ty(&l.bounded_ty, &r.bounded_ty)
&& over(&l.bounds, &r.bounds, eq_generic_bound)
},
(RegionPredicate(l), RegionPredicate(r)) => {
eq_id(l.lifetime.ident, r.lifetime.ident) && over(&l.bounds, &r.bounds, eq_generic_bound)
},
(EqPredicate(l), EqPredicate(r)) => eq_ty(&l.lhs_ty, &r.lhs_ty) && eq_ty(&l.rhs_ty, &r.rhs_ty),
_ => false,
}
}
pub fn eq_use_tree(l: &UseTree, r: &UseTree) -> bool {

View file

@ -242,14 +242,14 @@ fn fn_header_search_pat(header: FnHeader) -> Pat {
fn item_search_pat(item: &Item<'_>) -> (Pat, Pat) {
let (start_pat, end_pat) = match &item.kind {
ItemKind::ExternCrate(_) => (Pat::Str("extern"), Pat::Str(";")),
ItemKind::ExternCrate(..) => (Pat::Str("extern"), Pat::Str(";")),
ItemKind::Static(..) => (Pat::Str("static"), Pat::Str(";")),
ItemKind::Const(..) => (Pat::Str("const"), Pat::Str(";")),
ItemKind::Fn { sig, .. } => (fn_header_search_pat(sig.header), Pat::Str("")),
ItemKind::ForeignMod { .. } => (Pat::Str("extern"), Pat::Str("}")),
ItemKind::TyAlias(..) => (Pat::Str("type"), Pat::Str(";")),
ItemKind::Enum(..) => (Pat::Str("enum"), Pat::Str("}")),
ItemKind::Struct(VariantData::Struct { .. }, _) => (Pat::Str("struct"), Pat::Str("}")),
ItemKind::Struct(_, VariantData::Struct { .. }, _) => (Pat::Str("struct"), Pat::Str("}")),
ItemKind::Struct(..) => (Pat::Str("struct"), Pat::Str(";")),
ItemKind::Union(..) => (Pat::Str("union"), Pat::Str("}")),
ItemKind::Trait(_, Safety::Unsafe, ..)

View file

@ -291,6 +291,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
ExprKind::ConstBlock(_)
| ExprKind::Array(_)
| ExprKind::Tup(_)
| ExprKind::Use(..)
| ExprKind::Lit(_)
| ExprKind::Cast(..)
| ExprKind::Type(..)

View file

@ -393,6 +393,7 @@ impl HirEqInterExpr<'_, '_, '_> {
&& over(lf, rf, |l, r| self.eq_expr_field(l, r))
},
(&ExprKind::Tup(l_tup), &ExprKind::Tup(r_tup)) => self.eq_exprs(l_tup, r_tup),
(&ExprKind::Use(l_expr, _), &ExprKind::Use(r_expr, _)) => self.eq_expr(l_expr, r_expr),
(&ExprKind::Type(le, lt), &ExprKind::Type(re, rt)) => self.eq_expr(le, re) && self.eq_ty(lt, rt),
(&ExprKind::Unary(l_op, le), &ExprKind::Unary(r_op, re)) => l_op == r_op && self.eq_expr(le, re),
(&ExprKind::Yield(le, _), &ExprKind::Yield(re, _)) => return self.eq_expr(le, re),
@ -425,6 +426,7 @@ impl HirEqInterExpr<'_, '_, '_> {
| &ExprKind::Ret(..)
| &ExprKind::Struct(..)
| &ExprKind::Tup(..)
| &ExprKind::Use(..)
| &ExprKind::Type(..)
| &ExprKind::Unary(..)
| &ExprKind::Yield(..)
@ -1053,6 +1055,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
ExprKind::Tup(tup) => {
self.hash_exprs(tup);
},
ExprKind::Use(expr, _) => {
self.hash_expr(expr);
},
ExprKind::Unary(lop, le) => {
std::mem::discriminant(&lop).hash(&mut self.s);
self.hash_expr(le);
@ -1108,14 +1113,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
pub fn hash_ty_pat(&mut self, pat: &TyPat<'_>) {
std::mem::discriminant(&pat.kind).hash(&mut self.s);
match pat.kind {
TyPatKind::Range(s, e, i) => {
if let Some(s) = s {
self.hash_const_arg(s);
}
if let Some(e) = e {
self.hash_const_arg(e);
}
std::mem::discriminant(&i).hash(&mut self.s);
TyPatKind::Range(s, e) => {
self.hash_const_arg(s);
self.hash_const_arg(e);
},
TyPatKind::Err(_) => {},
}

View file

@ -31,7 +31,6 @@
// (Currently there is no way to opt into sysroot crates without `extern crate`.)
extern crate rustc_abi;
extern crate rustc_ast;
extern crate rustc_ast_pretty;
extern crate rustc_attr_parsing;
extern crate rustc_const_eval;
extern crate rustc_data_structures;
@ -645,7 +644,7 @@ fn local_item_children_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, name: Symb
let root_mod;
let item_kind = match tcx.hir_node_by_def_id(local_id) {
Node::Crate(r#mod) => {
root_mod = ItemKind::Mod(r#mod);
root_mod = ItemKind::Mod(Ident::dummy(), r#mod);
&root_mod
},
Node::Item(item) => &item.kind,
@ -662,10 +661,13 @@ fn local_item_children_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, name: Symb
};
match item_kind {
ItemKind::Mod(r#mod) => r#mod
ItemKind::Mod(_, r#mod) => r#mod
.item_ids
.iter()
.filter_map(|&item_id| res(tcx.hir_item(item_id).ident, item_id.owner_id))
.filter_map(|&item_id| {
let ident = tcx.hir_item(item_id).kind.ident()?;
res(ident, item_id.owner_id)
})
.collect(),
ItemKind::Impl(r#impl) => r#impl
.items
@ -1130,6 +1132,7 @@ pub fn can_move_expr_to_closure_no_visit<'tcx>(
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CaptureKind {
Value,
Use,
Ref(Mutability),
}
impl CaptureKind {
@ -1142,6 +1145,7 @@ impl std::ops::BitOr for CaptureKind {
fn bitor(self, rhs: Self) -> Self::Output {
match (self, rhs) {
(CaptureKind::Value, _) | (_, CaptureKind::Value) => CaptureKind::Value,
(CaptureKind::Use, _) | (_, CaptureKind::Use) => CaptureKind::Use,
(CaptureKind::Ref(Mutability::Mut), CaptureKind::Ref(_))
| (CaptureKind::Ref(_), CaptureKind::Ref(Mutability::Mut)) => CaptureKind::Ref(Mutability::Mut),
(CaptureKind::Ref(Mutability::Not), CaptureKind::Ref(Mutability::Not)) => CaptureKind::Ref(Mutability::Not),
@ -1165,7 +1169,6 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind {
pat.each_binding_or_first(&mut |_, id, span, _| match cx
.typeck_results()
.extract_binding_mode(cx.sess(), id, span)
.unwrap()
.0
{
ByRef::No if !is_copy(cx, cx.typeck_results().node_type(id)) => {
@ -1222,7 +1225,7 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind {
},
ExprKind::Let(let_expr) => {
let mutability = match pat_capture_kind(cx, let_expr.pat) {
CaptureKind::Value => Mutability::Not,
CaptureKind::Value | CaptureKind::Use => Mutability::Not,
CaptureKind::Ref(m) => m,
};
return CaptureKind::Ref(mutability);
@ -1231,7 +1234,7 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind {
let mut mutability = Mutability::Not;
for capture in arms.iter().map(|arm| pat_capture_kind(cx, arm.pat)) {
match capture {
CaptureKind::Value => break,
CaptureKind::Value | CaptureKind::Use => break,
CaptureKind::Ref(Mutability::Mut) => mutability = Mutability::Mut,
CaptureKind::Ref(Mutability::Not) => (),
}
@ -1241,7 +1244,7 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind {
_ => break,
},
Node::LetStmt(l) => match pat_capture_kind(cx, l.pat) {
CaptureKind::Value => break,
CaptureKind::Value | CaptureKind::Use => break,
capture @ CaptureKind::Ref(_) => return capture,
},
_ => break,
@ -1296,6 +1299,7 @@ pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'
if !self.locals.contains(&local_id) {
let capture = match capture.info.capture_kind {
UpvarCapture::ByValue => CaptureKind::Value,
UpvarCapture::ByUse => CaptureKind::Use,
UpvarCapture::ByRef(kind) => match kind {
BorrowKind::Immutable => CaptureKind::Ref(Mutability::Not),
BorrowKind::UniqueImmutable | BorrowKind::Mutable => {
@ -1415,9 +1419,8 @@ pub fn is_in_panic_handler(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
let parent_id = cx.tcx.hir_get_parent_item(expr.hir_id).def_id;
match cx.tcx.hir_node_by_def_id(parent_id) {
Node::Item(Item { ident, .. })
| Node::TraitItem(TraitItem { ident, .. })
| Node::ImplItem(ImplItem { ident, .. }) => Some(ident.name),
Node::Item(item) => item.kind.ident().map(|ident| ident.name),
Node::TraitItem(TraitItem { ident, .. }) | Node::ImplItem(ImplItem { ident, .. }) => Some(ident.name),
_ => None,
}
}
@ -2035,15 +2038,14 @@ pub fn has_attr(attrs: &[hir::Attribute], symbol: Symbol) -> bool {
}
pub fn has_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
find_attr!(cx.tcx.hir().attrs(hir_id), AttributeKind::Repr(..))
find_attr!(cx.tcx.hir_attrs(hir_id), AttributeKind::Repr(..))
}
pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool {
let map = &tcx.hir();
let mut prev_enclosing_node = None;
let mut enclosing_node = node;
while Some(enclosing_node) != prev_enclosing_node {
if has_attr(map.attrs(enclosing_node), symbol) {
if has_attr(tcx.hir_attrs(enclosing_node), symbol) {
return true;
}
prev_enclosing_node = Some(enclosing_node);
@ -2060,7 +2062,7 @@ pub fn in_automatically_derived(tcx: TyCtxt<'_>, id: HirId) -> bool {
.filter(|(_, node)| matches!(node, OwnerNode::Item(item) if matches!(item.kind, ItemKind::Impl(_))))
.any(|(id, _)| {
has_attr(
tcx.hir().attrs(tcx.local_def_id_to_hir_id(id.def_id)),
tcx.hir_attrs(tcx.local_def_id_to_hir_id(id.def_id)),
sym::automatically_derived,
)
})
@ -2355,16 +2357,14 @@ pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> {
pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
cx.tcx
.hir()
.attrs(hir::CRATE_HIR_ID)
.hir_attrs(hir::CRATE_HIR_ID)
.iter()
.any(|attr| attr.name_or_empty() == sym::no_std)
}
pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
cx.tcx
.hir()
.attrs(hir::CRATE_HIR_ID)
.hir_attrs(hir::CRATE_HIR_ID)
.iter()
.any(|attr| attr.name_or_empty() == sym::no_core)
}
@ -2648,18 +2648,17 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Sym
for id in tcx.hir_module_free_items(module) {
if matches!(tcx.def_kind(id.owner_id), DefKind::Const)
&& let item = tcx.hir_item(id)
&& let ItemKind::Const(ty, _generics, _body) = item.kind
&& let ItemKind::Const(ident, ty, _generics, _body) = item.kind
{
if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
// We could also check for the type name `test::TestDescAndFn`
if let Res::Def(DefKind::Struct, _) = path.res {
let has_test_marker = tcx
.hir()
.attrs(item.hir_id())
.hir_attrs(item.hir_id())
.iter()
.any(|a| a.has_name(sym::rustc_test_marker));
if has_test_marker {
names.push(item.ident.name);
names.push(ident.name);
}
}
}
@ -2683,10 +2682,10 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool {
// function scope
.any(|(_id, node)| {
if let Node::Item(item) = node {
if let ItemKind::Fn { .. } = item.kind {
if let ItemKind::Fn { ident, .. } = item.kind {
// Note that we have sorted the item names in the visitor,
// so the binary_search gets the same as `contains`, but faster.
return names.binary_search(&item.ident.name).is_ok();
return names.binary_search(&ident.name).is_ok();
}
}
false
@ -2699,7 +2698,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool {
/// This only checks directly applied attributes, to see if a node is inside a `#[cfg(test)]` parent
/// use [`is_in_cfg_test`]
pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool {
tcx.hir().attrs(id).iter().any(|attr| {
tcx.hir_attrs(id).iter().any(|attr| {
if attr.has_name(sym::cfg)
&& let Some(items) = attr.meta_item_list()
&& let [item] = &*items
@ -2724,12 +2723,10 @@ pub fn is_in_test(tcx: TyCtxt<'_>, hir_id: HirId) -> bool {
/// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied.
pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
let hir = tcx.hir();
tcx.has_attr(def_id, sym::cfg)
|| tcx
.hir_parent_iter(tcx.local_def_id_to_hir_id(def_id))
.flat_map(|(parent_id, _)| hir.attrs(parent_id))
.flat_map(|(parent_id, _)| tcx.hir_attrs(parent_id))
.any(|attr| attr.has_name(sym::cfg))
}
@ -3503,7 +3500,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
// a::b::c ::d::sym refers to
// e::f::sym:: ::
// result should be super::super::super::super::e::f
if let DefPathData::TypeNs(s) = l {
if let DefPathData::TypeNs(Some(s)) = l {
path.push(s.to_string());
}
if let DefPathData::TypeNs(_) = r {
@ -3514,7 +3511,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
// a::b::sym:: :: refers to
// c::d::e ::f::sym
// when looking at `f`
Left(DefPathData::TypeNs(sym)) => path.push(sym.to_string()),
Left(DefPathData::TypeNs(Some(sym))) => path.push(sym.to_string()),
// consider:
// a::b::c ::d::sym refers to
// e::f::sym:: ::
@ -3528,7 +3525,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
// `super` chain would be too long, just use the absolute path instead
once(String::from("crate"))
.chain(to.data.iter().filter_map(|el| {
if let DefPathData::TypeNs(sym) = el.data {
if let DefPathData::TypeNs(Some(sym)) = el.data {
Some(sym.to_string())
} else {
None

View file

@ -1,6 +1,6 @@
#![allow(clippy::similar_names)] // `expr` and `expn`
use std::sync::Arc;
use std::sync::{Arc, OnceLock};
use crate::get_unique_attr;
use crate::visitors::{Descend, for_each_expr_without_closures};
@ -8,7 +8,6 @@ use crate::visitors::{Descend, for_each_expr_without_closures};
use arrayvec::ArrayVec;
use rustc_ast::{FormatArgs, FormatArgument, FormatPlaceholder};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::OnceLock;
use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath};
use rustc_lint::{LateContext, LintContext};
use rustc_span::def_id::DefId;

View file

@ -6,8 +6,7 @@ use rustc_index::bit_set::DenseBitSet;
use rustc_lint::LateContext;
use rustc_middle::mir::visit::Visitor as _;
use rustc_middle::mir::{self, Mutability};
use rustc_middle::ty::visit::TypeVisitor;
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::ty::{self, TyCtxt, TypeVisitor};
use rustc_mir_dataflow::impls::MaybeStorageLive;
use rustc_mir_dataflow::{Analysis, ResultsCursor};
use std::borrow::Cow;

View file

@ -109,7 +109,7 @@ impl Msrv {
let start = cx.last_node_with_lint_attrs;
if let Some(msrv_attr) = once(start)
.chain(cx.tcx.hir_parent_id_iter(start))
.find_map(|id| parse_attrs(cx.tcx.sess, cx.tcx.hir().attrs(id)))
.find_map(|id| parse_attrs(cx.tcx.sess, cx.tcx.hir_attrs(id)))
{
return Some(msrv_attr);
}

View file

@ -4,9 +4,8 @@
use crate::source::{snippet, snippet_opt, snippet_with_applicability, snippet_with_context};
use crate::ty::expr_sig;
use crate::{get_parent_expr_for_hir, higher};
use rustc_ast::ast;
use rustc_ast::util::parser::AssocOp;
use rustc_ast::{ast, token};
use rustc_ast_pretty::pprust::token_kind_to_string;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::{Closure, ExprKind, HirId, MutTy, TyKind};
@ -114,10 +113,7 @@ impl<'a> Sugg<'a> {
/// function variants of `Sugg`, since these use different snippet functions.
fn hir_from_snippet(expr: &hir::Expr<'_>, mut get_snippet: impl FnMut(Span) -> Cow<'a, str>) -> Self {
if let Some(range) = higher::Range::hir(expr) {
let op = match range.limits {
ast::RangeLimits::HalfOpen => AssocOp::DotDot,
ast::RangeLimits::Closed => AssocOp::DotDotEq,
};
let op = AssocOp::Range(range.limits);
let start = range.start.map_or("".into(), |expr| get_snippet(expr.span));
let end = range.end.map_or("".into(), |expr| get_snippet(expr.span));
@ -151,6 +147,7 @@ impl<'a> Sugg<'a> {
| ExprKind::Become(..)
| ExprKind::Struct(..)
| ExprKind::Tup(..)
| ExprKind::Use(..)
| ExprKind::Err(_)
| ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(get_snippet(expr.span)),
ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet),
@ -158,16 +155,16 @@ impl<'a> Sugg<'a> {
Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span))
},
ExprKind::AssignOp(op, lhs, rhs) => {
Sugg::BinOp(hirbinop2assignop(op), get_snippet(lhs.span), get_snippet(rhs.span))
Sugg::BinOp(AssocOp::AssignOp(op.node), get_snippet(lhs.span), get_snippet(rhs.span))
},
ExprKind::Binary(op, lhs, rhs) => Sugg::BinOp(
AssocOp::from_ast_binop(op.node),
AssocOp::Binary(op.node),
get_snippet(lhs.span),
get_snippet(rhs.span),
),
ExprKind::Cast(lhs, ty) |
//FIXME(chenyukang), remove this after type ascription is removed from AST
ExprKind::Type(lhs, ty) => Sugg::BinOp(AssocOp::As, get_snippet(lhs.span), get_snippet(ty.span)),
ExprKind::Type(lhs, ty) => Sugg::BinOp(AssocOp::Cast, get_snippet(lhs.span), get_snippet(ty.span)),
}
}
@ -179,8 +176,6 @@ impl<'a> Sugg<'a> {
ctxt: SyntaxContext,
app: &mut Applicability,
) -> Self {
use rustc_ast::ast::RangeLimits;
let mut snippet = |span: Span| snippet_with_context(cx, span, ctxt, default, app).0;
match expr.kind {
@ -223,19 +218,15 @@ impl<'a> Sugg<'a> {
| ast::ExprKind::Try(..)
| ast::ExprKind::TryBlock(..)
| ast::ExprKind::Tup(..)
| ast::ExprKind::Use(..)
| ast::ExprKind::Array(..)
| ast::ExprKind::While(..)
| ast::ExprKind::Await(..)
| ast::ExprKind::Err(_)
| ast::ExprKind::Dummy
| ast::ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(snippet(expr.span)),
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp(
AssocOp::DotDot,
lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)),
rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)),
),
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::Closed) => Sugg::BinOp(
AssocOp::DotDotEq,
ast::ExprKind::Range(ref lhs, ref rhs, limits) => Sugg::BinOp(
AssocOp::Range(limits),
lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)),
rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)),
),
@ -245,19 +236,19 @@ impl<'a> Sugg<'a> {
snippet(rhs.span),
),
ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => Sugg::BinOp(
astbinop2assignop(op),
AssocOp::AssignOp(op.node),
snippet(lhs.span),
snippet(rhs.span),
),
ast::ExprKind::Binary(op, ref lhs, ref rhs) => Sugg::BinOp(
AssocOp::from_ast_binop(op.node),
AssocOp::Binary(op.node),
snippet(lhs.span),
snippet(rhs.span),
),
ast::ExprKind::Cast(ref lhs, ref ty) |
//FIXME(chenyukang), remove this after type ascription is removed from AST
ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp(
AssocOp::As,
AssocOp::Cast,
snippet(lhs.span),
snippet(ty.span),
),
@ -276,7 +267,7 @@ impl<'a> Sugg<'a> {
/// Convenience method to create the `<lhs> as <rhs>` suggestion.
pub fn as_ty<R: Display>(self, rhs: R) -> Sugg<'static> {
make_assoc(AssocOp::As, &self, &Sugg::NonParen(rhs.to_string().into()))
make_assoc(AssocOp::Cast, &self, &Sugg::NonParen(rhs.to_string().into()))
}
/// Convenience method to create the `&<expr>` suggestion.
@ -327,11 +318,8 @@ impl<'a> Sugg<'a> {
/// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>`
/// suggestion.
pub fn range(self, end: &Self, limit: ast::RangeLimits) -> Sugg<'static> {
match limit {
ast::RangeLimits::HalfOpen => make_assoc(AssocOp::DotDot, &self, end),
ast::RangeLimits::Closed => make_assoc(AssocOp::DotDotEq, &self, end),
}
pub fn range(self, end: &Self, limits: ast::RangeLimits) -> Sugg<'static> {
make_assoc(AssocOp::Range(limits), &self, end)
}
/// Adds parentheses to any expression that might need them. Suitable to the
@ -367,33 +355,11 @@ impl<'a> Sugg<'a> {
/// Generates a string from the operator and both sides.
fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String {
match op {
AssocOp::Add
| AssocOp::Subtract
| AssocOp::Multiply
| AssocOp::Divide
| AssocOp::Modulus
| AssocOp::LAnd
| AssocOp::LOr
| AssocOp::BitXor
| AssocOp::BitAnd
| AssocOp::BitOr
| AssocOp::ShiftLeft
| AssocOp::ShiftRight
| AssocOp::Equal
| AssocOp::Less
| AssocOp::LessEqual
| AssocOp::NotEqual
| AssocOp::Greater
| AssocOp::GreaterEqual => {
format!("{lhs} {} {rhs}", op.to_ast_binop().expect("Those are AST ops").as_str())
},
AssocOp::Binary(op) => format!("{lhs} {} {rhs}", op.as_str()),
AssocOp::Assign => format!("{lhs} = {rhs}"),
AssocOp::AssignOp(op) => {
format!("{lhs} {}= {rhs}", token_kind_to_string(&token::BinOp(op)))
},
AssocOp::As => format!("{lhs} as {rhs}"),
AssocOp::DotDot => format!("{lhs}..{rhs}"),
AssocOp::DotDotEq => format!("{lhs}..={rhs}"),
AssocOp::AssignOp(op) => format!("{lhs} {}= {rhs}", op.as_str()),
AssocOp::Cast => format!("{lhs} as {rhs}"),
AssocOp::Range(limits) => format!("{lhs}{}{rhs}", limits.as_str()),
}
}
@ -468,7 +434,7 @@ impl Neg for Sugg<'_> {
type Output = Sugg<'static>;
fn neg(self) -> Sugg<'static> {
match &self {
Self::BinOp(AssocOp::As, ..) => Sugg::MaybeParen(format!("-({self})").into()),
Self::BinOp(AssocOp::Cast, ..) => Sugg::MaybeParen(format!("-({self})").into()),
_ => make_unop("-", self),
}
}
@ -477,16 +443,17 @@ impl Neg for Sugg<'_> {
impl<'a> Not for Sugg<'a> {
type Output = Sugg<'a>;
fn not(self) -> Sugg<'a> {
use AssocOp::{Equal, Greater, GreaterEqual, Less, LessEqual, NotEqual};
use AssocOp::Binary;
use ast::BinOpKind::{Eq, Ge, Gt, Le, Lt, Ne};
if let Sugg::BinOp(op, lhs, rhs) = self {
let to_op = match op {
Equal => NotEqual,
NotEqual => Equal,
Less => GreaterEqual,
GreaterEqual => Less,
Greater => LessEqual,
LessEqual => Greater,
Binary(Eq) => Binary(Ne),
Binary(Ne) => Binary(Eq),
Binary(Lt) => Binary(Ge),
Binary(Ge) => Binary(Lt),
Binary(Gt) => Binary(Le),
Binary(Le) => Binary(Gt),
_ => return make_unop("!", Sugg::BinOp(op, lhs, rhs)),
};
Sugg::BinOp(to_op, lhs, rhs)
@ -538,7 +505,7 @@ pub fn make_unop(op: &str, expr: Sugg<'_>) -> Sugg<'static> {
pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> {
/// Returns `true` if the operator is a shift operator `<<` or `>>`.
fn is_shift(op: AssocOp) -> bool {
matches!(op, AssocOp::ShiftLeft | AssocOp::ShiftRight)
matches!(op, AssocOp::Binary(ast::BinOpKind::Shl | ast::BinOpKind::Shr))
}
/// Returns `true` if the operator is an arithmetic operator
@ -546,7 +513,13 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static>
fn is_arith(op: AssocOp) -> bool {
matches!(
op,
AssocOp::Add | AssocOp::Subtract | AssocOp::Multiply | AssocOp::Divide | AssocOp::Modulus
AssocOp::Binary(
ast::BinOpKind::Add
| ast::BinOpKind::Sub
| ast::BinOpKind::Mul
| ast::BinOpKind::Div
| ast::BinOpKind::Rem
)
)
}
@ -578,9 +551,9 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static>
Sugg::BinOp(op, lhs.into(), rhs.into())
}
/// Convenience wrapper around `make_assoc` and `AssocOp::from_ast_binop`.
/// Convenience wrapper around `make_assoc` and `AssocOp::Binary`.
pub fn make_binop(op: ast::BinOpKind, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> {
make_assoc(AssocOp::from_ast_binop(op), lhs, rhs)
make_assoc(AssocOp::Binary(op), lhs, rhs)
}
#[derive(PartialEq, Eq, Clone, Copy)]
@ -605,69 +578,17 @@ enum Associativity {
/// associative.
#[must_use]
fn associativity(op: AssocOp) -> Associativity {
use rustc_ast::util::parser::AssocOp::{
Add, As, Assign, AssignOp, BitAnd, BitOr, BitXor, Divide, DotDot, DotDotEq, Equal, Greater, GreaterEqual, LAnd,
LOr, Less, LessEqual, Modulus, Multiply, NotEqual, ShiftLeft, ShiftRight, Subtract,
};
use ast::BinOpKind::{Add, And, BitAnd, BitOr, BitXor, Div, Eq, Ge, Gt, Le, Lt, Mul, Ne, Or, Rem, Shl, Shr, Sub};
use rustc_ast::util::parser::AssocOp::{Assign, AssignOp, Binary, Cast, Range};
match op {
Assign | AssignOp(_) => Associativity::Right,
Add | BitAnd | BitOr | BitXor | LAnd | LOr | Multiply | As => Associativity::Both,
Divide | Equal | Greater | GreaterEqual | Less | LessEqual | Modulus | NotEqual | ShiftLeft | ShiftRight
| Subtract => Associativity::Left,
DotDot | DotDotEq => Associativity::None,
Binary(Add | BitAnd | BitOr | BitXor | And | Or | Mul) | Cast => Associativity::Both,
Binary(Div | Eq | Gt | Ge | Lt | Le | Rem | Ne | Shl | Shr | Sub) => Associativity::Left,
Range(_) => Associativity::None,
}
}
/// Converts a `hir::BinOp` to the corresponding assigning binary operator.
fn hirbinop2assignop(op: hir::BinOp) -> AssocOp {
use rustc_ast::token::BinOpToken::{And, Caret, Minus, Or, Percent, Plus, Shl, Shr, Slash, Star};
AssocOp::AssignOp(match op.node {
hir::BinOpKind::Add => Plus,
hir::BinOpKind::BitAnd => And,
hir::BinOpKind::BitOr => Or,
hir::BinOpKind::BitXor => Caret,
hir::BinOpKind::Div => Slash,
hir::BinOpKind::Mul => Star,
hir::BinOpKind::Rem => Percent,
hir::BinOpKind::Shl => Shl,
hir::BinOpKind::Shr => Shr,
hir::BinOpKind::Sub => Minus,
hir::BinOpKind::And
| hir::BinOpKind::Eq
| hir::BinOpKind::Ge
| hir::BinOpKind::Gt
| hir::BinOpKind::Le
| hir::BinOpKind::Lt
| hir::BinOpKind::Ne
| hir::BinOpKind::Or => panic!("This operator does not exist"),
})
}
/// Converts an `ast::BinOp` to the corresponding assigning binary operator.
fn astbinop2assignop(op: ast::BinOp) -> AssocOp {
use rustc_ast::ast::BinOpKind::{
Add, And, BitAnd, BitOr, BitXor, Div, Eq, Ge, Gt, Le, Lt, Mul, Ne, Or, Rem, Shl, Shr, Sub,
};
use rustc_ast::token::BinOpToken;
AssocOp::AssignOp(match op.node {
Add => BinOpToken::Plus,
BitAnd => BinOpToken::And,
BitOr => BinOpToken::Or,
BitXor => BinOpToken::Caret,
Div => BinOpToken::Slash,
Mul => BinOpToken::Star,
Rem => BinOpToken::Percent,
Shl => BinOpToken::Shl,
Shr => BinOpToken::Shr,
Sub => BinOpToken::Minus,
And | Eq | Ge | Gt | Le | Lt | Ne | Or => panic!("This operator does not exist"),
})
}
/// Returns the indentation before `span` if there are nothing but `[ \t]`
/// before it on its line.
fn indentation<T: LintContext>(cx: &T, span: Span) -> Option<String> {
@ -914,6 +835,8 @@ impl<'tcx> DerefDelegate<'_, 'tcx> {
impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {
if let PlaceBase::Local(id) = cmt.place.base {
let map = self.cx.tcx.hir();
@ -922,7 +845,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
let mut start_snip = snippet_with_applicability(self.cx, start_span, "..", &mut self.applicability);
// identifier referring to the variable currently triggered (i.e.: `fp`)
let ident_str = map.name(id).to_string();
let ident_str = self.cx.tcx.hir_name(id).to_string();
// full identifier that includes projection (i.e.: `fp.field`)
let ident_str_with_proj = snippet(self.cx, span, "..").to_string();
@ -951,7 +874,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
// item is used in a call
// i.e.: `Call`: `|x| please(x)` or `MethodCall`: `|x| [1, 2, 3].contains(x)`
ExprKind::Call(_, call_args) | ExprKind::MethodCall(_, _, call_args, _) => {
let expr = self.cx.tcx.hir().expect_expr(cmt.hir_id);
let expr = self.cx.tcx.hir_expect_expr(cmt.hir_id);
let arg_ty_kind = self.cx.typeck_results().expr_ty(expr).kind();
if matches!(arg_ty_kind, ty::Ref(_, _, Mutability::Not)) {
@ -1069,6 +992,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
mod test {
use super::Sugg;
use rustc_ast as ast;
use rustc_ast::util::parser::AssocOp;
use std::borrow::Cow;
@ -1086,15 +1010,15 @@ mod test {
#[test]
fn binop_maybe_par() {
let sugg = Sugg::BinOp(AssocOp::Add, "1".into(), "1".into());
let sugg = Sugg::BinOp(AssocOp::Binary(ast::BinOpKind::Add), "1".into(), "1".into());
assert_eq!("(1 + 1)", sugg.maybe_par().to_string());
let sugg = Sugg::BinOp(AssocOp::Add, "(1 + 1)".into(), "(1 + 1)".into());
let sugg = Sugg::BinOp(AssocOp::Binary(ast::BinOpKind::Add), "(1 + 1)".into(), "(1 + 1)".into());
assert_eq!("((1 + 1) + (1 + 1))", sugg.maybe_par().to_string());
}
#[test]
fn not_op() {
use AssocOp::{Add, Equal, Greater, GreaterEqual, LAnd, LOr, Less, LessEqual, NotEqual};
use ast::BinOpKind::{Add, And, Eq, Ge, Gt, Le, Lt, Ne, Or};
fn test_not(op: AssocOp, correct: &str) {
let sugg = Sugg::BinOp(op, "x".into(), "y".into());
@ -1102,16 +1026,16 @@ mod test {
}
// Invert the comparison operator.
test_not(Equal, "x != y");
test_not(NotEqual, "x == y");
test_not(Less, "x >= y");
test_not(LessEqual, "x > y");
test_not(Greater, "x <= y");
test_not(GreaterEqual, "x < y");
test_not(AssocOp::Binary(Eq), "x != y");
test_not(AssocOp::Binary(Ne), "x == y");
test_not(AssocOp::Binary(Lt), "x >= y");
test_not(AssocOp::Binary(Le), "x > y");
test_not(AssocOp::Binary(Gt), "x <= y");
test_not(AssocOp::Binary(Ge), "x < y");
// Other operators are inverted like !(..).
test_not(Add, "!(x + y)");
test_not(LAnd, "!(x && y)");
test_not(LOr, "!(x || y)");
test_not(AssocOp::Binary(Add), "!(x + y)");
test_not(AssocOp::Binary(And), "!(x && y)");
test_not(AssocOp::Binary(Or), "!(x || y)");
}
}

View file

@ -37,7 +37,7 @@ use crate::{def_path_def_ids, match_def_path, path_res};
mod type_certainty;
pub use type_certainty::expr_type_is_certain;
/// Lower a [`hir::Ty`] to a [`rustc_middle::Ty`].
/// Lower a [`hir::Ty`] to a [`rustc_middle::ty::Ty`].
pub fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
cx.maybe_typeck_results()
.and_then(|results| {

View file

@ -66,6 +66,8 @@ impl MutVarsDelegate {
impl<'tcx> Delegate<'tcx> for MutVarsDelegate {
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
fn use_cloned(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, bk: ty::BorrowKind) {
if bk == ty::BorrowKind::Mutable {
self.update(cmt);

View file

@ -648,6 +648,9 @@ pub fn for_each_unconsumed_temporary<'tcx, B>(
helper(typeck, true, arg, f)?;
}
},
ExprKind::Use(expr, _) => {
helper(typeck, true, expr, f)?;
},
ExprKind::Index(borrowed, consumed, _)
| ExprKind::Assign(borrowed, consumed, _)
| ExprKind::AssignOp(_, borrowed, consumed) => {

View file

@ -1,6 +1,6 @@
[toolchain]
# begin autogenerated nightly
channel = "nightly-2025-02-27"
channel = "nightly-2025-03-20"
# end autogenerated nightly
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
profile = "minimal"

View file

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

View file

@ -11,7 +11,6 @@ LL | impl PartialOrd for DeriveOrd {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: `-D clippy::derive-ord-xor-partial-ord` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::derive_ord_xor_partial_ord)]`
= note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
error: you are deriving `Ord` but have implemented `PartialOrd` explicitly
--> tests/ui/derive_ord_xor_partial_ord.rs:33:10
@ -24,7 +23,6 @@ note: `PartialOrd` implemented here
|
LL | impl PartialOrd<DeriveOrdWithExplicitTypeVariable> for DeriveOrdWithExplicitTypeVariable {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
error: you are implementing `Ord` explicitly but have derived `PartialOrd`
--> tests/ui/derive_ord_xor_partial_ord.rs:47:1
@ -42,7 +40,6 @@ note: `PartialOrd` implemented here
|
LL | #[derive(PartialOrd, PartialEq, Eq)]
| ^^^^^^^^^^
= note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
error: you are implementing `Ord` explicitly but have derived `PartialOrd`
--> tests/ui/derive_ord_xor_partial_ord.rs:69:5
@ -60,7 +57,6 @@ note: `PartialOrd` implemented here
|
LL | #[derive(PartialOrd, PartialEq, Eq)]
| ^^^^^^^^^^
= note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 4 previous errors

View file

@ -10,7 +10,6 @@ note: `PartialEq` implemented here
LL | impl PartialEq for Bar {
| ^^^^^^^^^^^^^^^^^^^^^^
= note: `#[deny(clippy::derived_hash_with_manual_eq)]` on by default
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
error: you are deriving `Hash` but have implemented `PartialEq` explicitly
--> tests/ui/derived_hash_with_manual_eq.rs:23:10
@ -23,7 +22,6 @@ note: `PartialEq` implemented here
|
LL | impl PartialEq<Baz> for Baz {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors

View file

@ -36,8 +36,6 @@ error: sub-expression diverges
|
LL | _ => true || panic!("boo"),
| ^^^^^^^^^^^^^
|
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: sub-expression diverges
--> tests/ui/diverging_sub_expression.rs:52:29

View file

@ -38,7 +38,6 @@ note: potential failure(s)
|
LL | panic!();
| ^^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: consider implementing `TryFrom` instead
--> tests/ui/fallible_impl_from.rs:40:1
@ -64,7 +63,6 @@ LL | } else if s.parse::<u32>().unwrap() != 42 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
LL | panic!("{:?}", s);
| ^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: consider implementing `TryFrom` instead
--> tests/ui/fallible_impl_from.rs:60:1
@ -85,7 +83,6 @@ LL | if s.parse::<u32>().ok().unwrap() != 42 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | panic!("{:?}", s);
| ^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 4 previous errors

View file

@ -23,7 +23,6 @@ LL | #[derive(Hash)]
= note: ... as (`hash("abc") != hash("abc".as_bytes())`
= help: consider either removing one of the `Borrow` implementations (`Borrow<str>` or `Borrow<[u8]>`) ...
= help: ... or not implementing `Hash` for this type
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
error: the semantics of `Borrow<T>` around `Hash` can't be satisfied when both `Borrow<str>` and `Borrow<[u8]>` are implemented
--> tests/ui/impl_hash_with_borrow_str_and_bytes.rs:117:6

View file

@ -192,6 +192,7 @@ impl Atpit for () {
type Tait = impl DerefMut;
//~^ implied_bounds_in_impls
#[define_opaque(Tait)]
fn define() -> Tait {
&mut [] as &mut [()]
}

View file

@ -192,6 +192,7 @@ impl Atpit for () {
type Tait = impl Deref + DerefMut;
//~^ implied_bounds_in_impls
#[define_opaque(Tait)]
fn define() -> Tait {
&mut [] as &mut [()]
}

View file

@ -6,15 +6,12 @@ LL | byte_view(panic!());
|
= note: `-D clippy::diverging-sub-expression` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::diverging_sub_expression)]`
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: sub-expression diverges
--> tests/ui/issue-7447.rs:29:19
|
LL | group_entries(panic!());
| ^^^^^^^^
|
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors

View file

@ -207,6 +207,7 @@ mod msrv {
mod with_ty_alias {
type Foo = impl std::fmt::Debug;
#[define_opaque(Foo)]
fn foo(_: Foo) {
let _: Foo = 1;
}

View file

@ -17,6 +17,7 @@ mod issue10041 {
struct Bomb2;
impl Bomb2 {
#[define_opaque(X)]
pub fn new() -> X {
//~^ ERROR: overflow evaluating the requirement
0i32

View file

@ -1,5 +1,5 @@
error[E0275]: overflow evaluating the requirement `<i32 as std::ops::Add>::Output == issue10041::X`
--> tests/ui/new_ret_no_self_overflow.rs:20:25
--> tests/ui/new_ret_no_self_overflow.rs:21:25
|
LL | pub fn new() -> X {
| ^

View file

@ -23,7 +23,6 @@ note: existing `clone` defined here
|
LL | #[derive(Clone)]
| ^^^^^
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
error: method's name is the same as an existing method in a trait
--> tests/ui/same_name_method.rs:46:13

Some files were not shown because too many files have changed in this diff Show more