mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-29 12:36:35 +03:00
Auto merge of #12331 - flip1995:rustup, r=flip1995
Rustup r? `@ghost` changelog: none
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
#![allow(
|
||||
clippy::must_use_candidate,
|
||||
clippy::missing_panics_doc,
|
||||
rustc::diagnostic_outside_of_impl,
|
||||
rustc::untranslatable_diagnostic,
|
||||
rustc::untranslatable_diagnostic_trivial
|
||||
)]
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) {
|
||||
} = self;
|
||||
|
||||
if !path.span.from_expansion()
|
||||
&& let Some(node) = cx.tcx.opt_hir_node(hir_id)
|
||||
&& let node = cx.tcx.hir_node(hir_id)
|
||||
&& !matches!(node, Node::Item(item) if matches!(item.kind, ItemKind::Use(_, _)))
|
||||
&& let [first, rest @ ..] = path.segments
|
||||
// Handle `::std`
|
||||
|
||||
@@ -46,11 +46,10 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
|
||||
return;
|
||||
};
|
||||
if let ConstantSource::Constant = source
|
||||
&& let Some(node) = cx.tcx.hir().find_parent(e.hir_id)
|
||||
&& let Node::Item(Item {
|
||||
kind: ItemKind::Const(..),
|
||||
..
|
||||
}) = node
|
||||
}) = cx.tcx.parent_hir_node(e.hir_id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1000,9 +1000,7 @@ fn check_clippy_cfg_attr(
|
||||
) {
|
||||
if cfg_attr.has_name(sym::clippy)
|
||||
&& let Some(ident) = behind_cfg_attr.ident()
|
||||
// FIXME: replace with `from_symbol` once https://github.com/rust-lang/rust/pull/121230
|
||||
// is merged.
|
||||
&& Level::from_str(ident.name.as_str()).is_some()
|
||||
&& Level::from_symbol(ident.name, Some(attr.id)).is_some()
|
||||
&& let Some(items) = behind_cfg_attr.meta_item_list()
|
||||
{
|
||||
let nb_items = items.len();
|
||||
|
||||
@@ -101,25 +101,22 @@ fn visit_ty(&mut self, t: &rustc_hir::Ty<'_>) {
|
||||
|
||||
fn given_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
match get_parent_node(cx.tcx, expr.hir_id) {
|
||||
Some(Node::Local(Local { ty: Some(ty), .. })) => {
|
||||
Node::Local(Local { ty: Some(ty), .. }) => {
|
||||
let mut v = InferVisitor::default();
|
||||
v.visit_ty(ty);
|
||||
!v.0
|
||||
},
|
||||
Some(
|
||||
Node::Expr(Expr {
|
||||
Node::Expr(Expr {
|
||||
kind: ExprKind::Call(path, args),
|
||||
..
|
||||
})
|
||||
| Node::Block(Block {
|
||||
expr: Some(Expr {
|
||||
kind: ExprKind::Call(path, args),
|
||||
..
|
||||
})
|
||||
| Node::Block(Block {
|
||||
expr:
|
||||
Some(Expr {
|
||||
kind: ExprKind::Call(path, args),
|
||||
..
|
||||
}),
|
||||
..
|
||||
}),
|
||||
) => {
|
||||
..
|
||||
}) => {
|
||||
if let Some(index) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
|
||||
&& let Some(sig) = expr_sig(cx, path)
|
||||
&& let Some(input) = sig.input(index)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize};
|
||||
use rustc_errors::{Applicability, Diagnostic, SuggestionStyle};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder, SuggestionStyle};
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind};
|
||||
use rustc_lint::LateContext;
|
||||
@@ -176,7 +176,7 @@ fn offer_suggestion(
|
||||
expr: &Expr<'_>,
|
||||
cast_expr: &Expr<'_>,
|
||||
cast_to_span: Span,
|
||||
diag: &mut Diagnostic,
|
||||
diag: &mut DiagnosticBuilder<'_, ()>,
|
||||
) {
|
||||
let cast_to_snip = snippet(cx, cast_to_span, "..");
|
||||
let suggestion = if cast_to_snip == "_" {
|
||||
|
||||
@@ -67,26 +67,20 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv
|
||||
}
|
||||
|
||||
fn is_child_of_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
let map = cx.tcx.hir();
|
||||
if let Some(parent_id) = map.opt_parent_id(expr.hir_id)
|
||||
&& let Some(parent) = cx.tcx.opt_hir_node(parent_id)
|
||||
{
|
||||
let expr = match parent {
|
||||
Node::Block(block) => {
|
||||
if let Some(parent_expr) = block.expr {
|
||||
parent_expr
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
Node::Expr(expr) => expr,
|
||||
_ => return false,
|
||||
};
|
||||
let parent = cx.tcx.parent_hir_node(expr.hir_id);
|
||||
let expr = match parent {
|
||||
Node::Block(block) => {
|
||||
if let Some(parent_expr) = block.expr {
|
||||
parent_expr
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
Node::Expr(expr) => expr,
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
matches!(expr.kind, ExprKind::Cast(..))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
matches!(expr.kind, ExprKind::Cast(..))
|
||||
}
|
||||
|
||||
/// Returns the type T of the pointed to *const [T] or *mut [T] and the mutability of the slice if
|
||||
|
||||
@@ -65,7 +65,7 @@ pub(super) fn check<'tcx>(
|
||||
&& let ExprKind::Path(qpath) = inner.kind
|
||||
&& let QPath::Resolved(None, Path { res, .. }) = qpath
|
||||
&& let Res::Local(hir_id) = res
|
||||
&& let parent = cx.tcx.hir().get_parent(*hir_id)
|
||||
&& let parent = cx.tcx.parent_hir_node(*hir_id)
|
||||
&& let Node::Local(local) = parent
|
||||
{
|
||||
if let Some(ty) = local.ty
|
||||
@@ -144,8 +144,7 @@ pub(super) fn check<'tcx>(
|
||||
|
||||
if cast_from.kind() == cast_to.kind() && !in_external_macro(cx.sess(), expr.span) {
|
||||
if let Some(id) = path_to_local(cast_expr)
|
||||
&& let Some(span) = cx.tcx.hir().opt_span(id)
|
||||
&& !span.eq_ctxt(cast_expr.span)
|
||||
&& !cx.tcx.hir().span(id).eq_ctxt(cast_expr.span)
|
||||
{
|
||||
// Binding context is different than the identifiers context.
|
||||
// Weird macro wizardry could be involved here.
|
||||
@@ -265,8 +264,7 @@ fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx
|
||||
}
|
||||
// Local usage
|
||||
} else if let Res::Local(hir_id) = res
|
||||
&& let Some(parent) = get_parent_node(cx.tcx, hir_id)
|
||||
&& let Node::Local(l) = parent
|
||||
&& let Node::Local(l) = get_parent_node(cx.tcx, hir_id)
|
||||
{
|
||||
if let Some(e) = l.init
|
||||
&& is_cast_from_ty_alias(cx, e, cast_from)
|
||||
|
||||
@@ -94,7 +94,7 @@ fn has_no_read_access<'tcx>(cx: &LateContext<'tcx>, id: HirId, block: &'tcx Bloc
|
||||
// `id` appearing in the left-hand side of an assignment is not a read access:
|
||||
//
|
||||
// id = ...; // Not reading `id`.
|
||||
if let Some(Node::Expr(parent)) = get_parent_node(cx.tcx, expr.hir_id)
|
||||
if let Node::Expr(parent) = get_parent_node(cx.tcx, expr.hir_id)
|
||||
&& let ExprKind::Assign(lhs, ..) = parent.kind
|
||||
&& path_to_local_id(lhs, id)
|
||||
{
|
||||
@@ -108,7 +108,7 @@ fn has_no_read_access<'tcx>(cx: &LateContext<'tcx>, id: HirId, block: &'tcx Bloc
|
||||
// Only assuming this for "official" methods defined on the type. For methods defined in extension
|
||||
// traits (identified as local, based on the orphan rule), pessimistically assume that they might
|
||||
// have side effects, so consider them a read.
|
||||
if let Some(Node::Expr(parent)) = get_parent_node(cx.tcx, expr.hir_id)
|
||||
if let Node::Expr(parent) = get_parent_node(cx.tcx, expr.hir_id)
|
||||
&& let ExprKind::MethodCall(_, receiver, _, _) = parent.kind
|
||||
&& path_to_local_id(receiver, id)
|
||||
&& let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(parent.hir_id)
|
||||
@@ -117,7 +117,7 @@ fn has_no_read_access<'tcx>(cx: &LateContext<'tcx>, id: HirId, block: &'tcx Bloc
|
||||
// The method call is a statement, so the return value is not used. That's not a read access:
|
||||
//
|
||||
// id.foo(args);
|
||||
if let Some(Node::Stmt(..)) = get_parent_node(cx.tcx, parent.hir_id) {
|
||||
if let Node::Stmt(..) = get_parent_node(cx.tcx, parent.hir_id) {
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
|
||||
|
||||
@@ -511,7 +511,8 @@ fn scan_block_for_eq<'tcx>(
|
||||
for stmt in &stmts[stmts.len() - init..=stmts.len() - offset] {
|
||||
if let StmtKind::Local(l) = stmt.kind {
|
||||
l.pat.each_binding_or_first(&mut |_, id, _, _| {
|
||||
eq.locals.remove(&id);
|
||||
// FIXME(rust/#120456) - is `swap_remove` correct?
|
||||
eq.locals.swap_remove(&id);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
ExprKind::Block(..) => {
|
||||
// If the `dbg!` macro is a "free" statement and not contained within other expressions,
|
||||
// remove the whole statement.
|
||||
if let Some(Node::Stmt(_)) = cx.tcx.hir().find_parent(expr.hir_id)
|
||||
if let Node::Stmt(_) = cx.tcx.parent_hir_node(expr.hir_id)
|
||||
&& let Some(semi_span) = cx.sess().source_map().mac_call_stmt_semi_span(macro_call.span)
|
||||
{
|
||||
(macro_call.span.to(semi_span), String::new())
|
||||
|
||||
@@ -131,7 +131,7 @@ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &Block<'tcx>) {
|
||||
// only when assigning `... = Default::default()`
|
||||
&& is_expr_default(expr, cx)
|
||||
&& let binding_type = cx.typeck_results().node_type(binding_id)
|
||||
&& let Some(adt) = binding_type.ty_adt_def()
|
||||
&& let ty::Adt(adt, args) = *binding_type.kind()
|
||||
&& adt.is_struct()
|
||||
&& let variant = adt.non_enum_variant()
|
||||
&& (adt.did().is_local() || !variant.is_field_list_non_exhaustive())
|
||||
@@ -144,7 +144,7 @@ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &Block<'tcx>) {
|
||||
.fields
|
||||
.iter()
|
||||
.all(|field| {
|
||||
is_copy(cx, cx.tcx.type_of(field.did).instantiate_identity())
|
||||
is_copy(cx, cx.tcx.type_of(field.did).instantiate(cx.tcx, args))
|
||||
})
|
||||
&& (!has_drop(cx, binding_type) || all_fields_are_copy)
|
||||
{
|
||||
|
||||
@@ -128,8 +128,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
|
||||
},
|
||||
_,
|
||||
) => {
|
||||
if let Some(parent) = self.cx.tcx.hir().find_parent(expr.hir_id)
|
||||
&& let Some(fn_sig) = parent.fn_sig()
|
||||
if let Some(fn_sig) = self.cx.tcx.parent_hir_node(expr.hir_id).fn_sig()
|
||||
&& let FnRetTy::Return(_ty) = fn_sig.decl.output
|
||||
{
|
||||
// We cannot check the exact type since it's a `hir::Ty`` which does not implement `is_numeric`
|
||||
|
||||
@@ -831,6 +831,7 @@ fn for_hir_ty<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Self {
|
||||
| TyKind::Typeof(..)
|
||||
| TyKind::TraitObject(..)
|
||||
| TyKind::InferDelegation(..)
|
||||
| TyKind::AnonAdt(..)
|
||||
| TyKind::Err(_) => Self::Reborrow,
|
||||
};
|
||||
}
|
||||
@@ -1008,7 +1009,7 @@ fn report<'tcx>(
|
||||
state.msg,
|
||||
|diag| {
|
||||
let (precedence, calls_field) = match get_parent_node(cx.tcx, data.first_expr.hir_id) {
|
||||
Some(Node::Expr(e)) => match e.kind {
|
||||
Node::Expr(e) => match e.kind {
|
||||
ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => (0, false),
|
||||
ExprKind::Call(..) => (PREC_POSTFIX, matches!(expr.kind, ExprKind::Field(..))),
|
||||
_ => (e.precedence().order(), false),
|
||||
@@ -1088,7 +1089,7 @@ fn report<'tcx>(
|
||||
//
|
||||
// e.g. `&mut x.y.z` where `x` is a union, and accessing `z` requires a
|
||||
// deref through `ManuallyDrop<_>` will not compile.
|
||||
let parent_id = cx.tcx.hir().parent_id(expr.hir_id);
|
||||
let parent_id = cx.tcx.parent_hir_id(expr.hir_id);
|
||||
if parent_id == data.first_expr.hir_id {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
&& let Some(def_id) = trait_ref.trait_def_id()
|
||||
&& cx.tcx.is_diagnostic_item(sym::Default, def_id)
|
||||
&& let impl_item_hir = child.id.hir_id()
|
||||
&& let Some(Node::ImplItem(impl_item)) = cx.tcx.opt_hir_node(impl_item_hir)
|
||||
&& let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir)
|
||||
&& let ImplItemKind::Fn(_, b) = &impl_item.kind
|
||||
&& let Body { value: func_expr, .. } = cx.tcx.hir().body(*b)
|
||||
&& let &Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use clippy_utils::macros::macro_backtrace;
|
||||
use rustc_ast::Attribute;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Diagnostic;
|
||||
use rustc_errors::DiagnosticBuilder;
|
||||
use rustc_hir::def_id::DefIdMap;
|
||||
use rustc_hir::{
|
||||
Expr, ExprKind, ForeignItem, HirId, ImplItem, Item, ItemKind, OwnerId, Pat, Path, Stmt, TraitItem, Ty,
|
||||
@@ -89,7 +89,7 @@ fn check(&mut self, cx: &LateContext<'_>, span: Span, derive_src: Option<OwnerId
|
||||
if let Some(&index) = self.disallowed.get(&mac.def_id) {
|
||||
let conf = &self.conf_disallowed[index];
|
||||
let msg = format!("use of a disallowed macro `{}`", conf.path());
|
||||
let add_note = |diag: &mut Diagnostic| {
|
||||
let add_note = |diag: &mut DiagnosticBuilder<'_, _>| {
|
||||
if let Some(reason) = conf.reason() {
|
||||
diag.note(reason);
|
||||
}
|
||||
|
||||
@@ -144,8 +144,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
// }
|
||||
fn is_single_call_in_arm<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'_>, drop_expr: &'tcx Expr<'_>) -> bool {
|
||||
if matches!(arg.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)) {
|
||||
let parent_node = get_parent_node(cx.tcx, drop_expr.hir_id);
|
||||
if let Some(Node::Arm(Arm { body, .. })) = &parent_node {
|
||||
if let Node::Arm(Arm { body, .. }) = get_parent_node(cx.tcx, drop_expr.hir_id) {
|
||||
return body.hir_id == drop_expr.hir_id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
|
||||
}) = item.kind
|
||||
&& trait_ref.trait_def_id() == cx.tcx.lang_items().drop_trait()
|
||||
&& let impl_item_hir = child.id.hir_id()
|
||||
&& let Some(Node::ImplItem(impl_item)) = cx.tcx.opt_hir_node(impl_item_hir)
|
||||
&& let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir)
|
||||
&& let ImplItemKind::Fn(_, b) = &impl_item.kind
|
||||
&& let Body { value: func_expr, .. } = cx.tcx.hir().body(*b)
|
||||
&& let func_expr = peel_blocks(func_expr)
|
||||
|
||||
@@ -123,22 +123,23 @@ fn check_fn(
|
||||
|
||||
// TODO: Replace with Map::is_argument(..) when it's fixed
|
||||
fn is_argument(tcx: TyCtxt<'_>, id: HirId) -> bool {
|
||||
match tcx.opt_hir_node(id) {
|
||||
Some(Node::Pat(Pat {
|
||||
match tcx.hir_node(id) {
|
||||
Node::Pat(Pat {
|
||||
kind: PatKind::Binding(..),
|
||||
..
|
||||
})) => (),
|
||||
}) => (),
|
||||
_ => return false,
|
||||
}
|
||||
|
||||
matches!(tcx.hir().find_parent(id), Some(Node::Param(_)))
|
||||
matches!(tcx.parent_hir_node(id), Node::Param(_))
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
|
||||
fn consume(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId) {
|
||||
if cmt.place.projections.is_empty() {
|
||||
if let PlaceBase::Local(lid) = cmt.place.base {
|
||||
self.set.remove(&lid);
|
||||
// FIXME(rust/#120456) - is `swap_remove` correct?
|
||||
self.set.swap_remove(&lid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -146,7 +147,8 @@ fn consume(&mut self, cmt: &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 {
|
||||
self.set.remove(&lid);
|
||||
// FIXME(rust/#120456) - is `swap_remove` correct?
|
||||
self.set.swap_remove(&lid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,8 +158,8 @@ fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId) {
|
||||
let map = &self.cx.tcx.hir();
|
||||
if is_argument(self.cx.tcx, cmt.hir_id) {
|
||||
// Skip closure arguments
|
||||
let parent_id = map.parent_id(cmt.hir_id);
|
||||
if let Some(Node::Expr(..)) = map.find_parent(parent_id) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ fn look_in_block<'tcx, 'hir>(cx: &LateContext<'tcx>, kind: &'tcx ExprKind<'hir>)
|
||||
// Find id of the local that expr_end_of_block resolves to
|
||||
&& let ExprKind::Path(QPath::Resolved(None, expr_path)) = expr_end_of_block.kind
|
||||
&& let Res::Local(expr_res) = expr_path.res
|
||||
&& let Some(Node::Pat(res_pat)) = cx.tcx.opt_hir_node(expr_res)
|
||||
&& let Node::Pat(res_pat) = cx.tcx.hir_node(expr_res)
|
||||
|
||||
// Find id of the local we found in the block
|
||||
&& let PatKind::Binding(BindingAnnotation::NONE, local_hir_id, _ident, None) = local.pat.kind
|
||||
|
||||
@@ -53,7 +53,7 @@ pub(super) fn check_fn<'tcx>(cx: &LateContext<'_>, kind: &'tcx FnKind<'_>, body:
|
||||
|
||||
pub(super) fn check_impl_item(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) {
|
||||
if let ImplItemKind::Fn(_, body_id) = impl_item.kind
|
||||
&& let hir::Node::Item(item) = cx.tcx.hir().get_parent(impl_item.hir_id())
|
||||
&& let hir::Node::Item(item) = cx.tcx.parent_hir_node(impl_item.hir_id())
|
||||
&& let hir::ItemKind::Impl(impl_) = item.kind
|
||||
&& let hir::Impl { of_trait, .. } = *impl_
|
||||
&& of_trait.is_none()
|
||||
@@ -72,7 +72,7 @@ pub(super) fn check_impl_item(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) {
|
||||
pub(super) fn check_trait_item(cx: &LateContext<'_>, trait_item: &TraitItem<'_>, avoid_breaking_exported_api: bool) {
|
||||
if !avoid_breaking_exported_api
|
||||
&& let TraitItemKind::Fn(_, _) = trait_item.kind
|
||||
&& let hir::Node::Item(item) = cx.tcx.hir().get_parent(trait_item.hir_id())
|
||||
&& let hir::Node::Item(item) = cx.tcx.parent_hir_node(trait_item.hir_id())
|
||||
// ^^ (Will always be a trait)
|
||||
&& !item.vis_span.is_empty() // Is public
|
||||
&& !is_in_test_function(cx.tcx, trait_item.hir_id())
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use rustc_errors::Diagnostic;
|
||||
use rustc_errors::DiagnosticBuilder;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
@@ -135,7 +135,7 @@ fn check_result_large_err<'tcx>(cx: &LateContext<'tcx>, err_ty: Ty<'tcx>, hir_ty
|
||||
RESULT_LARGE_ERR,
|
||||
hir_ty_span,
|
||||
"the `Err`-variant returned from this function is very large",
|
||||
|diag: &mut Diagnostic| {
|
||||
|diag: &mut DiagnosticBuilder<'_, ()>| {
|
||||
diag.span_label(hir_ty_span, format!("the `Err`-variant is at least {ty_size} bytes"));
|
||||
diag.help(format!("try reducing the size of `{err_ty}`, for example by boxing large elements or replacing it with `Box<{err_ty}>`"));
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use clippy_utils::{higher, SpanlessEq};
|
||||
use rustc_errors::Diagnostic;
|
||||
use rustc_errors::DiagnosticBuilder;
|
||||
use rustc_hir::intravisit::{self as visit, Visitor};
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
@@ -59,7 +59,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||
arm_visit.visit_expr(if_else);
|
||||
|
||||
if let Some(arm_mutex) = arm_visit.found_mutex_if_same_as(op_mutex) {
|
||||
let diag = |diag: &mut Diagnostic| {
|
||||
let diag = |diag: &mut DiagnosticBuilder<'_, ()>| {
|
||||
diag.span_label(
|
||||
op_mutex.span,
|
||||
"this Mutex will remain locked for the entire `if let`-block...",
|
||||
|
||||
@@ -41,8 +41,8 @@ fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx hir::Pat<'tcx>) {
|
||||
return;
|
||||
}
|
||||
|
||||
match cx.tcx.hir().get_parent(pat.hir_id) {
|
||||
Node::Param(param) if matches!(cx.tcx.hir().get_parent(param.hir_id), Node::Item(_)) => {
|
||||
match cx.tcx.parent_hir_node(pat.hir_id) {
|
||||
Node::Param(param) if matches!(cx.tcx.parent_hir_node(param.hir_id), Node::Item(_)) => {
|
||||
// Ignore function parameters
|
||||
return;
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::borrow::Cow;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use rustc_errors::Diagnostic;
|
||||
use rustc_errors::DiagnosticBuilder;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::{walk_body, walk_expr, walk_inf, walk_ty, Visitor};
|
||||
use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind};
|
||||
@@ -65,7 +65,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
|
||||
fn suggestion(
|
||||
cx: &LateContext<'_>,
|
||||
diag: &mut Diagnostic,
|
||||
diag: &mut DiagnosticBuilder<'_, ()>,
|
||||
generics_span: Span,
|
||||
generics_suggestion_span: Span,
|
||||
target: &ImplicitHasherType<'_>,
|
||||
|
||||
@@ -106,7 +106,8 @@ fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap<hir
|
||||
}
|
||||
if sub_pat.is_some() {
|
||||
removed_pat.insert(value_hir_id);
|
||||
slices.remove(&value_hir_id);
|
||||
// FIXME(rust/#120456) - is `swap_remove` correct?
|
||||
slices.swap_remove(&value_hir_id);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -242,29 +243,27 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
|
||||
} = *self;
|
||||
|
||||
if let Some(use_info) = slice_lint_info.get_mut(&local_id)
|
||||
// Check if this is even a local we're interested in
|
||||
|
||||
&& let map = cx.tcx.hir()
|
||||
|
||||
// Checking for slice indexing
|
||||
&& let parent_id = map.parent_id(expr.hir_id)
|
||||
&& let Some(hir::Node::Expr(parent_expr)) = cx.tcx.opt_hir_node(parent_id)
|
||||
&& let parent_id = cx.tcx.parent_hir_id(expr.hir_id)
|
||||
&& let hir::Node::Expr(parent_expr) = cx.tcx.hir_node(parent_id)
|
||||
&& let hir::ExprKind::Index(_, index_expr, _) = parent_expr.kind
|
||||
&& let Some(Constant::Int(index_value)) = constant(cx, cx.typeck_results(), index_expr)
|
||||
&& let Ok(index_value) = index_value.try_into()
|
||||
&& index_value < max_suggested_slice
|
||||
|
||||
// Make sure that this slice index is read only
|
||||
&& let maybe_addrof_id = map.parent_id(parent_id)
|
||||
&& let Some(hir::Node::Expr(maybe_addrof_expr)) = cx.tcx.opt_hir_node(maybe_addrof_id)
|
||||
&& let hir::Node::Expr(maybe_addrof_expr) = cx.tcx.parent_hir_node(parent_id)
|
||||
&& let hir::ExprKind::AddrOf(_kind, hir::Mutability::Not, _inner_expr) = maybe_addrof_expr.kind
|
||||
{
|
||||
use_info.index_use.push((index_value, map.span(parent_expr.hir_id)));
|
||||
use_info
|
||||
.index_use
|
||||
.push((index_value, cx.tcx.hir().span(parent_expr.hir_id)));
|
||||
return;
|
||||
}
|
||||
|
||||
// The slice was used for something other than indexing
|
||||
self.slice_lint_info.remove(&local_id);
|
||||
// FIXME(rust/#120456) - is `swap_remove` correct?
|
||||
self.slice_lint_info.swap_remove(&local_id);
|
||||
}
|
||||
intravisit::walk_expr(self, expr);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'tcx>
|
||||
if matches!(name, "iter" | "iter_mut")
|
||||
&& !matches!(
|
||||
get_parent_node(cx.tcx, item.hir_id()),
|
||||
Some(Node::Item(Item { kind: ItemKind::Impl(i), .. })) if i.of_trait.is_some()
|
||||
Node::Item(Item { kind: ItemKind::Impl(i), .. }) if i.of_trait.is_some()
|
||||
)
|
||||
{
|
||||
if let ImplItemKind::Fn(fn_sig, _) = &item.kind {
|
||||
|
||||
@@ -269,7 +269,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::ImplItem<'
|
||||
// }
|
||||
let span_behind_impl = cx
|
||||
.tcx
|
||||
.def_span(cx.tcx.hir().parent_id(item.hir_id()).owner.def_id)
|
||||
.def_span(cx.tcx.parent_hir_id(item.hir_id()).owner.def_id)
|
||||
.shrink_to_lo();
|
||||
|
||||
let sugg = format!(
|
||||
|
||||
@@ -147,9 +147,9 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>)
|
||||
&& let Some(output) =
|
||||
parse_len_output(cx, cx.tcx.fn_sig(item.owner_id).instantiate_identity().skip_binder())
|
||||
{
|
||||
let (name, kind) = match cx.tcx.opt_hir_node(ty_hir_id) {
|
||||
Some(Node::ForeignItem(x)) => (x.ident.name, "extern type"),
|
||||
Some(Node::Item(x)) => match x.kind {
|
||||
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"),
|
||||
|
||||
@@ -10,7 +10,12 @@
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![recursion_limit = "512"]
|
||||
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
||||
#![allow(clippy::missing_docs_in_private_items, clippy::must_use_candidate)]
|
||||
#![allow(
|
||||
clippy::missing_docs_in_private_items,
|
||||
clippy::must_use_candidate,
|
||||
rustc::diagnostic_outside_of_impl,
|
||||
rustc::untranslatable_diagnostic
|
||||
)]
|
||||
#![warn(trivial_casts, trivial_numeric_casts)]
|
||||
// warn on lints, that are included in `rust-lang/rust`s bootstrap
|
||||
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||
|
||||
@@ -176,7 +176,7 @@ fn check_fn_inner<'tcx>(
|
||||
_ => None,
|
||||
});
|
||||
for bound in lifetimes {
|
||||
if !bound.is_static() && !bound.is_elided() {
|
||||
if bound.res != LifetimeName::Static && !bound.is_elided() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -285,7 +285,7 @@ fn elision_suggestions(
|
||||
.iter()
|
||||
.filter(|usage| named_lifetime(usage).map_or(false, |id| elidable_lts.contains(&id)))
|
||||
.map(|usage| {
|
||||
match cx.tcx.hir().get_parent(usage.hir_id) {
|
||||
match cx.tcx.parent_hir_node(usage.hir_id) {
|
||||
Node::Ty(Ty {
|
||||
kind: TyKind::Ref(..), ..
|
||||
}) => {
|
||||
|
||||
@@ -62,8 +62,7 @@ fn emit_lint(cx: &LateContext<'_>, vec: &Expr<'_>, pushed_item: &Expr<'_>, ctxt:
|
||||
if let Node::Pat(pat) = node
|
||||
&& let PatKind::Binding(bind_ann, ..) = pat.kind
|
||||
&& !matches!(bind_ann, BindingAnnotation(_, Mutability::Mut))
|
||||
&& let parent_node = cx.tcx.hir().parent_id(hir_id)
|
||||
&& let Some(Node::Local(parent_let_expr)) = cx.tcx.opt_hir_node(parent_node)
|
||||
&& let Node::Local(parent_let_expr) = cx.tcx.parent_hir_node(hir_id)
|
||||
&& let Some(init) = parent_let_expr.init
|
||||
{
|
||||
match init.kind {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
peel_blocks_with_stmt, MaybePath,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use rustc_errors::{Applicability, Diagnostic};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::{Arm, BinOpKind, Block, Expr, ExprKind, HirId, PatKind, PathSegment, PrimTy, QPath, StmtKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
@@ -163,7 +163,7 @@ fn emit_suggestion<'tcx>(cx: &LateContext<'tcx>, suggestion: &ClampSuggestion<'t
|
||||
};
|
||||
let suggestion = format!("{assignment}{input}.clamp({min}, {max}){semicolon}");
|
||||
let msg = "clamp-like pattern without using clamp function";
|
||||
let lint_builder = |d: &mut Diagnostic| {
|
||||
let lint_builder = |d: &mut DiagnosticBuilder<'_, ()>| {
|
||||
d.span_suggestion(*span, "replace with clamp", suggestion, Applicability::MaybeIncorrect);
|
||||
if *is_float {
|
||||
d.note("clamp will panic if max < min, min.is_nan(), or max.is_nan()")
|
||||
|
||||
@@ -68,8 +68,8 @@ fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
|
||||
&& let ExprKind::MethodCall(seg, build_hasher, [], _) = init.kind
|
||||
&& seg.ident.name == sym!(build_hasher)
|
||||
|
||||
&& let Node::Stmt(local_stmt) = cx.tcx.hir().get_parent(local.hir_id)
|
||||
&& let Node::Block(block) = cx.tcx.hir().get_parent(local_stmt.hir_id)
|
||||
&& let Node::Stmt(local_stmt) = cx.tcx.parent_hir_node(local.hir_id)
|
||||
&& let Node::Block(block) = cx.tcx.parent_hir_node(local_stmt.hir_id)
|
||||
|
||||
&& let mut stmts = block.stmts.iter()
|
||||
.skip_while(|stmt| stmt.hir_id != local_stmt.hir_id)
|
||||
@@ -91,7 +91,7 @@ fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
|
||||
|
||||
// `hasher.finish()`, may be anywhere in a statement or the trailing expr of the block
|
||||
&& let Some(path_expr) = local_used_once(cx, (maybe_finish_stmt, block.expr), hasher)
|
||||
&& let Node::Expr(finish_expr) = cx.tcx.hir().get_parent(path_expr.hir_id)
|
||||
&& let Node::Expr(finish_expr) = cx.tcx.parent_hir_node(path_expr.hir_id)
|
||||
&& !finish_expr.span.from_expansion()
|
||||
&& let ExprKind::MethodCall(seg, _, [], _) = finish_expr.kind
|
||||
&& seg.ident.name == sym!(finish)
|
||||
|
||||
@@ -76,12 +76,12 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
// Also ensures the const is nonzero since zero can't be a divisor
|
||||
&& const1 == const2 && const2 == const3
|
||||
&& let Some(hir_id) = path_to_local(expr3)
|
||||
&& let Some(Node::Pat(_)) = cx.tcx.opt_hir_node(hir_id)
|
||||
&& let Node::Pat(_) = cx.tcx.hir_node(hir_id)
|
||||
{
|
||||
// Apply only to params or locals with annotated types
|
||||
match cx.tcx.hir().find_parent(hir_id) {
|
||||
Some(Node::Param(..)) => (),
|
||||
Some(Node::Local(local)) => {
|
||||
match cx.tcx.parent_hir_node(hir_id) {
|
||||
Node::Param(..) => (),
|
||||
Node::Local(local) => {
|
||||
let Some(ty) = local.ty else { return };
|
||||
if matches!(ty.kind, TyKind::Infer) {
|
||||
return;
|
||||
|
||||
@@ -307,7 +307,8 @@ fn from_pat(cx: &LateContext<'_>, arena: &'a DroplessArena, pat: &'a Pat<'_>) ->
|
||||
LitKind::Char(val) => Self::LitInt(val.into()),
|
||||
LitKind::Int(val, _) => Self::LitInt(val.get()),
|
||||
LitKind::Bool(val) => Self::LitBool(val),
|
||||
LitKind::Float(..) | LitKind::Err => Self::Wild,
|
||||
LitKind::Float(..) => Self::Wild,
|
||||
LitKind::Err(guar) => Self::Err(guar),
|
||||
},
|
||||
_ => Self::Wild,
|
||||
},
|
||||
@@ -427,6 +428,7 @@ fn pat_contains_local(pat: &Pat<'_>, id: HirId) -> bool {
|
||||
/// Returns true if all the bindings in the `Pat` are in `ids` and vice versa
|
||||
fn bindings_eq(pat: &Pat<'_>, mut ids: HirIdSet) -> bool {
|
||||
let mut result = true;
|
||||
pat.each_binding_or_first(&mut |_, id, _, _| result &= ids.remove(&id));
|
||||
// FIXME(rust/#120456) - is `swap_remove` correct?
|
||||
pat.each_binding_or_first(&mut |_, id, _, _| result &= ids.swap_remove(&id));
|
||||
result && ids.is_empty()
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
|
||||
.to_string();
|
||||
|
||||
// Do we need to add ';' to suggestion ?
|
||||
if let Node::Stmt(stmt) = cx.tcx.hir().get_parent(expr.hir_id)
|
||||
if let Node::Stmt(stmt) = cx.tcx.parent_hir_node(expr.hir_id)
|
||||
&& let StmtKind::Expr(_) = stmt.kind
|
||||
&& match match_body.kind {
|
||||
// We don't need to add a ; to blocks, unless that block is from a macro expansion
|
||||
@@ -146,18 +146,16 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
|
||||
|
||||
/// Returns true if the `ex` match expression is in a local (`let`) or assign expression
|
||||
fn opt_parent_assign_span<'a>(cx: &LateContext<'a>, ex: &Expr<'a>) -> Option<AssignmentExpr> {
|
||||
let map = &cx.tcx.hir();
|
||||
|
||||
if let Some(Node::Expr(parent_arm_expr)) = map.find_parent(ex.hir_id) {
|
||||
return match map.find_parent(parent_arm_expr.hir_id) {
|
||||
Some(Node::Local(parent_let_expr)) => Some(AssignmentExpr::Local {
|
||||
if let Node::Expr(parent_arm_expr) = cx.tcx.parent_hir_node(ex.hir_id) {
|
||||
return match cx.tcx.parent_hir_node(parent_arm_expr.hir_id) {
|
||||
Node::Local(parent_let_expr) => Some(AssignmentExpr::Local {
|
||||
span: parent_let_expr.span,
|
||||
pat_span: parent_let_expr.pat.span(),
|
||||
}),
|
||||
Some(Node::Expr(Expr {
|
||||
Node::Expr(Expr {
|
||||
kind: ExprKind::Assign(parent_assign_expr, match_expr, _),
|
||||
..
|
||||
})) => Some(AssignmentExpr::Assign {
|
||||
}) => Some(AssignmentExpr::Assign {
|
||||
span: parent_assign_expr.span,
|
||||
match_span: match_expr.span,
|
||||
}),
|
||||
@@ -191,7 +189,7 @@ fn sugg_with_curlies<'a>(
|
||||
|
||||
// If the parent is already an arm, and the body is another match statement,
|
||||
// we need curly braces around suggestion
|
||||
if let Node::Arm(arm) = &cx.tcx.hir().get_parent(match_expr.hir_id) {
|
||||
if let Node::Arm(arm) = &cx.tcx.parent_hir_node(match_expr.hir_id) {
|
||||
if let ExprKind::Match(..) = arm.body.kind {
|
||||
cbrace_end = format!("\n{indent}}}");
|
||||
// Fix body indent due to the match
|
||||
|
||||
@@ -123,37 +123,35 @@ fn strip_return<'hir>(expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> {
|
||||
/// Manually check for coercion casting by checking if the type of the match operand or let expr
|
||||
/// differs with the assigned local variable or the function return type.
|
||||
fn expr_ty_matches_p_ty(cx: &LateContext<'_>, expr: &Expr<'_>, p_expr: &Expr<'_>) -> bool {
|
||||
if let Some(p_node) = get_parent_node(cx.tcx, p_expr.hir_id) {
|
||||
match p_node {
|
||||
// Compare match_expr ty with local in `let local = match match_expr {..}`
|
||||
Node::Local(local) => {
|
||||
let results = cx.typeck_results();
|
||||
return same_type_and_consts(results.node_type(local.hir_id), results.expr_ty(expr));
|
||||
},
|
||||
// compare match_expr ty with RetTy in `fn foo() -> RetTy`
|
||||
Node::Item(item) => {
|
||||
if let ItemKind::Fn(..) = item.kind {
|
||||
let output = cx
|
||||
.tcx
|
||||
.fn_sig(item.owner_id)
|
||||
.instantiate_identity()
|
||||
.output()
|
||||
.skip_binder();
|
||||
return same_type_and_consts(output, cx.typeck_results().expr_ty(expr));
|
||||
}
|
||||
},
|
||||
// check the parent expr for this whole block `{ match match_expr {..} }`
|
||||
Node::Block(block) => {
|
||||
if let Some(block_parent_expr) = get_parent_expr_for_hir(cx, block.hir_id) {
|
||||
return expr_ty_matches_p_ty(cx, expr, block_parent_expr);
|
||||
}
|
||||
},
|
||||
// recursively call on `if xxx {..}` etc.
|
||||
Node::Expr(p_expr) => {
|
||||
return expr_ty_matches_p_ty(cx, expr, p_expr);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
match get_parent_node(cx.tcx, p_expr.hir_id) {
|
||||
// Compare match_expr ty with local in `let local = match match_expr {..}`
|
||||
Node::Local(local) => {
|
||||
let results = cx.typeck_results();
|
||||
return same_type_and_consts(results.node_type(local.hir_id), results.expr_ty(expr));
|
||||
},
|
||||
// compare match_expr ty with RetTy in `fn foo() -> RetTy`
|
||||
Node::Item(item) => {
|
||||
if let ItemKind::Fn(..) = item.kind {
|
||||
let output = cx
|
||||
.tcx
|
||||
.fn_sig(item.owner_id)
|
||||
.instantiate_identity()
|
||||
.output()
|
||||
.skip_binder();
|
||||
return same_type_and_consts(output, cx.typeck_results().expr_ty(expr));
|
||||
}
|
||||
},
|
||||
// check the parent expr for this whole block `{ match match_expr {..} }`
|
||||
Node::Block(block) => {
|
||||
if let Some(block_parent_expr) = get_parent_expr_for_hir(cx, block.hir_id) {
|
||||
return expr_ty_matches_p_ty(cx, expr, block_parent_expr);
|
||||
}
|
||||
},
|
||||
// recursively call on `if xxx {..}` etc.
|
||||
Node::Expr(p_expr) => {
|
||||
return expr_ty_matches_p_ty(cx, expr, p_expr);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ fn get_pat_binding<'tcx>(
|
||||
return span.map(|span| PatBindingInfo {
|
||||
span,
|
||||
byref_ident,
|
||||
is_field: matches!(cx.tcx.hir().get_parent(local), Node::PatField(_)),
|
||||
is_field: matches!(cx.tcx.parent_hir_node(local), Node::PatField(_)),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::{indent_of, snippet};
|
||||
use clippy_utils::{get_attr, is_lint_allowed};
|
||||
use rustc_errors::{Applicability, Diagnostic};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||
use rustc_hir::intravisit::{walk_expr, Visitor};
|
||||
use rustc_hir::{Arm, Expr, ExprKind, MatchSource};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
@@ -37,7 +37,12 @@ pub(super) fn check<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
fn set_diagnostic<'tcx>(diag: &mut Diagnostic, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, found: FoundSigDrop) {
|
||||
fn set_diagnostic<'tcx>(
|
||||
diag: &mut DiagnosticBuilder<'_, ()>,
|
||||
cx: &LateContext<'tcx>,
|
||||
expr: &'tcx Expr<'tcx>,
|
||||
found: FoundSigDrop,
|
||||
) {
|
||||
if found.lint_suggestion == LintSuggestion::MoveAndClone {
|
||||
// If our suggestion is to move and clone, then we want to leave it to the user to
|
||||
// decide how to address this lint, since it may be that cloning is inappropriate.
|
||||
|
||||
@@ -49,7 +49,7 @@ pub(super) fn check(
|
||||
|
||||
if is_copy(cx, ty) {
|
||||
let parent_is_suffix_expr = match get_parent_node(cx.tcx, expr.hir_id) {
|
||||
Some(Node::Expr(parent)) => match parent.kind {
|
||||
Node::Expr(parent) => match parent.kind {
|
||||
// &*x is a nop, &x.clone() is not
|
||||
ExprKind::AddrOf(..) => return,
|
||||
// (*x).func() is useless, x.clone().func() can work in case func borrows self
|
||||
@@ -70,7 +70,7 @@ pub(super) fn check(
|
||||
_ => false,
|
||||
},
|
||||
// local binding capturing a reference
|
||||
Some(Node::Local(l)) if matches!(l.pat.kind, PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..)) => {
|
||||
Node::Local(l) if matches!(l.pat.kind, PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..)) => {
|
||||
return;
|
||||
},
|
||||
_ => false,
|
||||
|
||||
@@ -44,7 +44,7 @@ pub(super) fn check<'tcx>(
|
||||
// add note if not multi-line
|
||||
span_lint_and_then(cx, FILTER_NEXT, expr.span, msg, |diag| {
|
||||
let (applicability, pat) = if let Some(id) = path_to_local(recv)
|
||||
&& let Some(hir::Node::Pat(pat)) = cx.tcx.opt_hir_node(id)
|
||||
&& let hir::Node::Pat(pat) = cx.tcx.hir_node(id)
|
||||
&& let hir::PatKind::Binding(BindingAnnotation(_, Mutability::Not), _, ident, _) = pat.kind
|
||||
{
|
||||
(Applicability::Unspecified, Some((pat.span, ident)))
|
||||
|
||||
@@ -4458,7 +4458,7 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
_ => {},
|
||||
},
|
||||
("drain", ..) => {
|
||||
if let Node::Stmt(Stmt { hir_id: _, kind, .. }) = cx.tcx.hir().get_parent(expr.hir_id)
|
||||
if let Node::Stmt(Stmt { hir_id: _, kind, .. }) = cx.tcx.parent_hir_node(expr.hir_id)
|
||||
&& matches!(kind, StmtKind::Semi(_))
|
||||
&& args.len() <= 1
|
||||
{
|
||||
|
||||
@@ -28,104 +28,102 @@ pub(super) fn check<'tcx>(
|
||||
iter_expr: &'tcx Expr<'tcx>,
|
||||
call_span: Span,
|
||||
) {
|
||||
if let Some(parent) = get_parent_node(cx.tcx, collect_expr.hir_id) {
|
||||
match parent {
|
||||
Node::Expr(parent) => {
|
||||
check_collect_into_intoiterator(cx, parent, collect_expr, call_span, iter_expr);
|
||||
match get_parent_node(cx.tcx, collect_expr.hir_id) {
|
||||
Node::Expr(parent) => {
|
||||
check_collect_into_intoiterator(cx, parent, collect_expr, call_span, iter_expr);
|
||||
|
||||
if let ExprKind::MethodCall(name, _, args @ ([] | [_]), _) = parent.kind {
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let name = name.ident.as_str();
|
||||
let collect_ty = cx.typeck_results().expr_ty(collect_expr);
|
||||
if let ExprKind::MethodCall(name, _, args @ ([] | [_]), _) = parent.kind {
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let name = name.ident.as_str();
|
||||
let collect_ty = cx.typeck_results().expr_ty(collect_expr);
|
||||
|
||||
let sugg: String = match name {
|
||||
"len" => {
|
||||
if let Some(adt) = collect_ty.ty_adt_def()
|
||||
&& matches!(
|
||||
cx.tcx.get_diagnostic_name(adt.did()),
|
||||
Some(sym::Vec | sym::VecDeque | sym::LinkedList | sym::BinaryHeap)
|
||||
)
|
||||
{
|
||||
"count()".into()
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
},
|
||||
"is_empty"
|
||||
if is_is_empty_sig(cx, parent.hir_id)
|
||||
&& iterates_same_ty(cx, cx.typeck_results().expr_ty(iter_expr), collect_ty) =>
|
||||
let sugg: String = match name {
|
||||
"len" => {
|
||||
if let Some(adt) = collect_ty.ty_adt_def()
|
||||
&& matches!(
|
||||
cx.tcx.get_diagnostic_name(adt.did()),
|
||||
Some(sym::Vec | sym::VecDeque | sym::LinkedList | sym::BinaryHeap)
|
||||
)
|
||||
{
|
||||
"next().is_none()".into()
|
||||
},
|
||||
"contains" => {
|
||||
if is_contains_sig(cx, parent.hir_id, iter_expr)
|
||||
&& let Some(arg) = args.first()
|
||||
{
|
||||
let (span, prefix) = if let ExprKind::AddrOf(_, _, arg) = arg.kind {
|
||||
(arg.span, "")
|
||||
} else {
|
||||
(arg.span, "*")
|
||||
};
|
||||
let snip = snippet_with_applicability(cx, span, "??", &mut app);
|
||||
format!("any(|x| x == {prefix}{snip})")
|
||||
"count()".into()
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
},
|
||||
"is_empty"
|
||||
if is_is_empty_sig(cx, parent.hir_id)
|
||||
&& iterates_same_ty(cx, cx.typeck_results().expr_ty(iter_expr), collect_ty) =>
|
||||
{
|
||||
"next().is_none()".into()
|
||||
},
|
||||
"contains" => {
|
||||
if is_contains_sig(cx, parent.hir_id, iter_expr)
|
||||
&& let Some(arg) = args.first()
|
||||
{
|
||||
let (span, prefix) = if let ExprKind::AddrOf(_, _, arg) = arg.kind {
|
||||
(arg.span, "")
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
},
|
||||
_ => return,
|
||||
};
|
||||
(arg.span, "*")
|
||||
};
|
||||
let snip = snippet_with_applicability(cx, span, "??", &mut app);
|
||||
format!("any(|x| x == {prefix}{snip})")
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
},
|
||||
_ => return,
|
||||
};
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
NEEDLESS_COLLECT,
|
||||
call_span.with_hi(parent.span.hi()),
|
||||
NEEDLESS_COLLECT_MSG,
|
||||
"replace with",
|
||||
sugg,
|
||||
app,
|
||||
);
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
NEEDLESS_COLLECT,
|
||||
call_span.with_hi(parent.span.hi()),
|
||||
NEEDLESS_COLLECT_MSG,
|
||||
"replace with",
|
||||
sugg,
|
||||
app,
|
||||
);
|
||||
}
|
||||
},
|
||||
Node::Local(l) => {
|
||||
if let PatKind::Binding(BindingAnnotation::NONE | BindingAnnotation::MUT, id, _, None) = l.pat.kind
|
||||
&& let ty = cx.typeck_results().expr_ty(collect_expr)
|
||||
&& [sym::Vec, sym::VecDeque, sym::BinaryHeap, sym::LinkedList]
|
||||
.into_iter()
|
||||
.any(|item| is_type_diagnostic_item(cx, ty, item))
|
||||
&& let iter_ty = cx.typeck_results().expr_ty(iter_expr)
|
||||
&& let Some(block) = get_enclosing_block(cx, l.hir_id)
|
||||
&& let Some(iter_calls) = detect_iter_and_into_iters(block, id, cx, get_captured_ids(cx, iter_ty))
|
||||
&& let [iter_call] = &*iter_calls
|
||||
{
|
||||
let mut used_count_visitor = UsedCountVisitor { cx, id, count: 0 };
|
||||
walk_block(&mut used_count_visitor, block);
|
||||
if used_count_visitor.count > 1 {
|
||||
return;
|
||||
}
|
||||
},
|
||||
Node::Local(l) => {
|
||||
if let PatKind::Binding(BindingAnnotation::NONE | BindingAnnotation::MUT, id, _, None) = l.pat.kind
|
||||
&& let ty = cx.typeck_results().expr_ty(collect_expr)
|
||||
&& [sym::Vec, sym::VecDeque, sym::BinaryHeap, sym::LinkedList]
|
||||
.into_iter()
|
||||
.any(|item| is_type_diagnostic_item(cx, ty, item))
|
||||
&& let iter_ty = cx.typeck_results().expr_ty(iter_expr)
|
||||
&& let Some(block) = get_enclosing_block(cx, l.hir_id)
|
||||
&& let Some(iter_calls) = detect_iter_and_into_iters(block, id, cx, get_captured_ids(cx, iter_ty))
|
||||
&& let [iter_call] = &*iter_calls
|
||||
{
|
||||
let mut used_count_visitor = UsedCountVisitor { cx, id, count: 0 };
|
||||
walk_block(&mut used_count_visitor, block);
|
||||
if used_count_visitor.count > 1 {
|
||||
return;
|
||||
}
|
||||
|
||||
// Suggest replacing iter_call with iter_replacement, and removing stmt
|
||||
let mut span = MultiSpan::from_span(name_span);
|
||||
span.push_span_label(iter_call.span, "the iterator could be used here instead");
|
||||
span_lint_hir_and_then(
|
||||
cx,
|
||||
super::NEEDLESS_COLLECT,
|
||||
collect_expr.hir_id,
|
||||
span,
|
||||
NEEDLESS_COLLECT_MSG,
|
||||
|diag| {
|
||||
let iter_replacement =
|
||||
format!("{}{}", Sugg::hir(cx, iter_expr, ".."), iter_call.get_iter_method(cx));
|
||||
diag.multipart_suggestion(
|
||||
iter_call.get_suggestion_text(),
|
||||
vec![(l.span, String::new()), (iter_call.span, iter_replacement)],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
// Suggest replacing iter_call with iter_replacement, and removing stmt
|
||||
let mut span = MultiSpan::from_span(name_span);
|
||||
span.push_span_label(iter_call.span, "the iterator could be used here instead");
|
||||
span_lint_hir_and_then(
|
||||
cx,
|
||||
super::NEEDLESS_COLLECT,
|
||||
collect_expr.hir_id,
|
||||
span,
|
||||
NEEDLESS_COLLECT_MSG,
|
||||
|diag| {
|
||||
let iter_replacement =
|
||||
format!("{}{}", Sugg::hir(cx, iter_expr, ".."), iter_call.get_iter_method(cx));
|
||||
diag.multipart_suggestion(
|
||||
iter_call.get_suggestion_text(),
|
||||
vec![(l.span, String::new()), (iter_call.span, iter_replacement)],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> {
|
||||
|
||||
fn visit_path(&mut self, path: &Path<'tcx>, _: HirId) {
|
||||
if let Res::Local(local_id) = path.res
|
||||
&& let Some(Node::Pat(pat)) = self.cx.tcx.opt_hir_node(local_id)
|
||||
&& let Node::Pat(pat) = self.cx.tcx.hir_node(local_id)
|
||||
&& let PatKind::Binding(_, local_id, ..) = pat.kind
|
||||
{
|
||||
self.identifiers.insert(local_id);
|
||||
@@ -166,7 +166,7 @@ fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'_>) {
|
||||
&& let ExprKind::Path(ref path) = expr.kind
|
||||
&& let QPath::Resolved(_, path) = path
|
||||
&& let Res::Local(local_id) = path.res
|
||||
&& let Some(Node::Pat(pat)) = self.cx.tcx.opt_hir_node(local_id)
|
||||
&& let Node::Pat(pat) = self.cx.tcx.hir_node(local_id)
|
||||
&& let PatKind::Binding(_, local_id, ..) = pat.kind
|
||||
&& self.identifiers.contains(&local_id)
|
||||
{
|
||||
|
||||
@@ -21,9 +21,9 @@ fn is_unwrap_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
|
||||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, receiver: &Expr<'_>) {
|
||||
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(receiver).peel_refs(), sym::RwLock)
|
||||
&& let Node::Expr(unwrap_call_expr) = cx.tcx.hir().get_parent(expr.hir_id)
|
||||
&& let Node::Expr(unwrap_call_expr) = cx.tcx.parent_hir_node(expr.hir_id)
|
||||
&& is_unwrap_call(cx, unwrap_call_expr)
|
||||
&& let parent = cx.tcx.hir().get_parent(unwrap_call_expr.hir_id)
|
||||
&& let parent = cx.tcx.parent_hir_node(unwrap_call_expr.hir_id)
|
||||
&& let Node::Local(local) = parent
|
||||
&& let Some(mir) = enclosing_mir(cx.tcx, expr.hir_id)
|
||||
&& let Some((local, _)) = mir
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use rustc_errors::{Applicability, Diagnostic};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::{sym, Span};
|
||||
use {rustc_ast as ast, rustc_hir as hir};
|
||||
@@ -22,7 +22,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx hir::Expr<'_>, arg
|
||||
SUSPICIOUS_COMMAND_ARG_SPACE,
|
||||
arg.span,
|
||||
"single argument that looks like it should be multiple arguments",
|
||||
|diag: &mut Diagnostic| {
|
||||
|diag: &mut DiagnosticBuilder<'_, ()>| {
|
||||
diag.multipart_suggestion_verbose(
|
||||
"consider splitting the argument",
|
||||
vec![(span, "args".to_string()), (arg.span, format!("[{arg1:?}, {arg2:?}]"))],
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
/// Changing `fold` to `sum` needs it sometimes when the return type can't be
|
||||
/// inferred. This checks for some common cases where it can be safely omitted
|
||||
fn needs_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
|
||||
let parent = cx.tcx.hir().get_parent(expr.hir_id);
|
||||
let parent = cx.tcx.parent_hir_node(expr.hir_id);
|
||||
|
||||
// some common cases where turbofish isn't needed:
|
||||
// - assigned to a local variable with a type annotation
|
||||
|
||||
@@ -76,7 +76,7 @@ pub(super) fn check(
|
||||
(expr.span.with_lo(call_args[0].span.hi()), String::new()),
|
||||
];
|
||||
// try to also remove the unsafe block if present
|
||||
if let hir::Node::Block(block) = cx.tcx.hir().get_parent(expr.hir_id)
|
||||
if let hir::Node::Block(block) = cx.tcx.parent_hir_node(expr.hir_id)
|
||||
&& let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = block.rules
|
||||
{
|
||||
suggs.extend([
|
||||
|
||||
@@ -99,10 +99,10 @@ fn visit_id(&mut self, hir_id: HirId) {
|
||||
let node = if hir_id.local_id == ItemLocalId::from_u32(0) {
|
||||
// In this case, we can just use `find`, `Owner`'s `node` field is private anyway so we can't
|
||||
// reimplement it even if we wanted to
|
||||
cx.tcx.opt_hir_node(hir_id)
|
||||
Some(cx.tcx.hir_node(hir_id))
|
||||
} else {
|
||||
let owner = cx.tcx.hir_owner_nodes(hir_id.owner);
|
||||
owner.nodes.get(hir_id.local_id).copied().flatten().map(|p| p.node)
|
||||
owner.nodes.get(hir_id.local_id).copied().map(|p| p.node)
|
||||
};
|
||||
let Some(node) = node else {
|
||||
return;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
use rustc_ast::{LitKind, RangeLimits};
|
||||
use rustc_data_structures::packed::Pu128;
|
||||
use rustc_data_structures::unhash::UnhashMap;
|
||||
use rustc_errors::{Applicability, Diagnostic};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||
use rustc_hir::{BinOp, Block, Body, Expr, ExprKind, UnOp};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
@@ -67,7 +67,7 @@
|
||||
|
||||
fn report_lint<F>(cx: &LateContext<'_>, full_span: Span, msg: &str, indexes: &[Span], f: F)
|
||||
where
|
||||
F: FnOnce(&mut Diagnostic),
|
||||
F: FnOnce(&mut DiagnosticBuilder<'_, ()>),
|
||||
{
|
||||
span_lint_and_then(cx, MISSING_ASSERTS_FOR_INDEXING, full_span, msg, |diag| {
|
||||
f(diag);
|
||||
|
||||
@@ -206,18 +206,14 @@ fn visit_block(&mut self, _: &'tcx Block<'_>) {
|
||||
///
|
||||
/// When such a read is found, the lint is triggered.
|
||||
fn check_for_unsequenced_reads(vis: &mut ReadVisitor<'_, '_>) {
|
||||
let map = &vis.cx.tcx.hir();
|
||||
let mut cur_id = vis.write_expr.hir_id;
|
||||
loop {
|
||||
let parent_id = map.parent_id(cur_id);
|
||||
let parent_id = vis.cx.tcx.parent_hir_id(cur_id);
|
||||
if parent_id == cur_id {
|
||||
break;
|
||||
}
|
||||
let Some(parent_node) = vis.cx.tcx.opt_hir_node(parent_id) else {
|
||||
break;
|
||||
};
|
||||
|
||||
let stop_early = match parent_node {
|
||||
let stop_early = match vis.cx.tcx.hir_node(parent_id) {
|
||||
Node::Expr(expr) => check_expr(vis, expr),
|
||||
Node::Stmt(stmt) => check_stmt(vis, stmt),
|
||||
Node::Item(_) => {
|
||||
|
||||
@@ -139,7 +139,7 @@ fn condition_needs_parentheses(e: &Expr<'_>) -> bool {
|
||||
fn is_parent_stmt(cx: &LateContext<'_>, id: HirId) -> bool {
|
||||
matches!(
|
||||
get_parent_node(cx.tcx, id),
|
||||
Some(Node::Stmt(..) | Node::Block(Block { stmts: &[], .. }))
|
||||
Node::Stmt(..) | Node::Block(Block { stmts: &[], .. })
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ fn check_fn(
|
||||
};
|
||||
|
||||
// Exclude non-inherent impls
|
||||
if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) {
|
||||
if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) {
|
||||
if matches!(
|
||||
item.kind,
|
||||
ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
|
||||
@@ -236,11 +236,10 @@ fn check_fn(
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||
// #11182; do not lint if mutability is required elsewhere
|
||||
if let ExprKind::Path(..) = expr.kind
|
||||
&& let Some(parent) = get_parent_node(cx.tcx, expr.hir_id)
|
||||
&& let ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(expr).kind()
|
||||
&& let Some(def_id) = def_id.as_local()
|
||||
{
|
||||
if let Node::Expr(e) = parent
|
||||
if let Node::Expr(e) = get_parent_node(cx.tcx, expr.hir_id)
|
||||
&& let ExprKind::Call(call, _) = e.kind
|
||||
&& call.hir_id == expr.hir_id
|
||||
{
|
||||
@@ -382,7 +381,8 @@ fn consume(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, id: HirId) {
|
||||
self.add_mutably_used_var(*vid);
|
||||
}
|
||||
self.prev_bind = None;
|
||||
self.prev_move_to_closure.remove(vid);
|
||||
// FIXME(rust/#120456) - is `swap_remove` correct?
|
||||
self.prev_move_to_closure.swap_remove(vid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item,
|
||||
};
|
||||
use rustc_ast::ast::Attribute;
|
||||
use rustc_errors::{Applicability, Diagnostic};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||
use rustc_hir::intravisit::FnKind;
|
||||
use rustc_hir::{
|
||||
BindingAnnotation, Body, FnDecl, GenericArg, HirId, HirIdSet, Impl, ItemKind, LangItem, Mutability, Node, PatKind,
|
||||
@@ -100,7 +100,7 @@ fn check_fn(
|
||||
}
|
||||
|
||||
// Exclude non-inherent impls
|
||||
if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) {
|
||||
if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) {
|
||||
if matches!(
|
||||
item.kind,
|
||||
ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
|
||||
@@ -196,7 +196,7 @@ fn check_fn(
|
||||
&& !moved_vars.contains(&canonical_id)
|
||||
{
|
||||
// Dereference suggestion
|
||||
let sugg = |diag: &mut Diagnostic| {
|
||||
let sugg = |diag: &mut DiagnosticBuilder<'_, ()>| {
|
||||
if let ty::Adt(def, ..) = ty.kind() {
|
||||
if let Some(span) = cx.tcx.hir().span_if_local(def.did()) {
|
||||
if type_allowed_to_implement_copy(
|
||||
|
||||
@@ -94,7 +94,8 @@ fn check_block(&mut self, _: &LateContext<'tcx>, _: &'tcx rustc_hir::Block<'tcx>
|
||||
|
||||
fn check_block_post(&mut self, cx: &LateContext<'tcx>, _: &'tcx rustc_hir::Block<'tcx>) {
|
||||
for hir_id in self.local_bindings.pop().unwrap() {
|
||||
if let Some(span) = self.underscore_bindings.remove(&hir_id) {
|
||||
// FIXME(rust/#120456) - is `swap_remove` correct?
|
||||
if let Some(span) = self.underscore_bindings.swap_remove(&hir_id) {
|
||||
span_lint_hir(
|
||||
cx,
|
||||
NO_EFFECT_UNDERSCORE_BINDING,
|
||||
@@ -108,7 +109,8 @@ fn check_block_post(&mut self, cx: &LateContext<'tcx>, _: &'tcx rustc_hir::Block
|
||||
|
||||
fn check_expr(&mut self, _: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
|
||||
if let Some(def_id) = path_to_local(expr) {
|
||||
self.underscore_bindings.remove(&def_id);
|
||||
// FIXME(rust/#120456) - is `swap_remove` correct?
|
||||
self.underscore_bindings.swap_remove(&def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -138,7 +140,7 @@ fn check_no_effect(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool {
|
||||
for parent in cx.tcx.hir().parent_iter(stmt.hir_id) {
|
||||
if let Node::Item(item) = parent.1
|
||||
&& let ItemKind::Fn(..) = item.kind
|
||||
&& let Some(Node::Block(block)) = get_parent_node(cx.tcx, stmt.hir_id)
|
||||
&& let Node::Block(block) = get_parent_node(cx.tcx, stmt.hir_id)
|
||||
&& let [.., final_stmt] = block.stmts
|
||||
&& final_stmt.hir_id == stmt.hir_id
|
||||
{
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
impl LateLintPass<'_> for NonCanonicalImpls {
|
||||
#[expect(clippy::too_many_lines)]
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &ImplItem<'_>) {
|
||||
let Some(Node::Item(item)) = get_parent_node(cx.tcx, impl_item.hir_id()) else {
|
||||
let Node::Item(item) = get_parent_node(cx.tcx, impl_item.hir_id()) else {
|
||||
return;
|
||||
};
|
||||
let Some(trait_impl) = cx.tcx.impl_trait_ref(item.owner_id).map(EarlyBinder::skip_binder) else {
|
||||
|
||||
@@ -449,11 +449,11 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
let mut dereferenced_expr = expr;
|
||||
let mut needs_check_adjustment = true;
|
||||
loop {
|
||||
let parent_id = cx.tcx.hir().parent_id(cur_expr.hir_id);
|
||||
let parent_id = cx.tcx.parent_hir_id(cur_expr.hir_id);
|
||||
if parent_id == cur_expr.hir_id {
|
||||
break;
|
||||
}
|
||||
if let Some(Node::Expr(parent_expr)) = cx.tcx.opt_hir_node(parent_id) {
|
||||
if let Node::Expr(parent_expr) = cx.tcx.hir_node(parent_id) {
|
||||
match &parent_expr.kind {
|
||||
ExprKind::AddrOf(..) => {
|
||||
// `&e` => `e` must be referenced.
|
||||
|
||||
@@ -153,7 +153,8 @@ fn remove_by_id(&mut self, id: HirId) {
|
||||
param.uses = Vec::new();
|
||||
let key = (param.fn_id, param.idx);
|
||||
self.by_fn.remove(&key);
|
||||
self.by_id.remove(&id);
|
||||
// FIXME(rust/#120456) - is `swap_remove` correct?
|
||||
self.by_id.swap_remove(&id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,23 +228,23 @@ fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'tcx>) {
|
||||
// `skip_params` is either `0` or `1` to skip the `self` parameter in trait functions.
|
||||
// It can't be renamed, and it can't be removed without removing it from multiple functions.
|
||||
let (fn_id, fn_kind, skip_params) = match get_parent_node(cx.tcx, body.value.hir_id) {
|
||||
Some(Node::Item(i)) => (i.owner_id.to_def_id(), FnKind::Fn, 0),
|
||||
Some(Node::TraitItem(&TraitItem {
|
||||
Node::Item(i) => (i.owner_id.to_def_id(), FnKind::Fn, 0),
|
||||
Node::TraitItem(&TraitItem {
|
||||
kind: TraitItemKind::Fn(ref sig, _),
|
||||
owner_id,
|
||||
..
|
||||
})) => (
|
||||
}) => (
|
||||
owner_id.to_def_id(),
|
||||
FnKind::TraitFn,
|
||||
usize::from(sig.decl.implicit_self.has_implicit_self()),
|
||||
),
|
||||
Some(Node::ImplItem(&ImplItem {
|
||||
Node::ImplItem(&ImplItem {
|
||||
kind: ImplItemKind::Fn(ref sig, _),
|
||||
owner_id,
|
||||
..
|
||||
})) => {
|
||||
}) => {
|
||||
#[allow(trivial_casts)]
|
||||
if let Some(Node::Item(item)) = get_parent_node(cx.tcx, owner_id.into())
|
||||
if let Node::Item(item) = get_parent_node(cx.tcx, owner_id.into())
|
||||
&& let Some(trait_ref) = cx
|
||||
.tcx
|
||||
.impl_trait_ref(item.owner_id)
|
||||
|
||||
@@ -34,7 +34,7 @@ pub(super) fn check<'tcx>(
|
||||
}
|
||||
|
||||
fn used_in_comparison_with_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
let Some(Node::Expr(parent_expr)) = cx.tcx.hir().find_parent(expr.hir_id) else {
|
||||
let Node::Expr(parent_expr) = cx.tcx.parent_hir_node(expr.hir_id) else {
|
||||
return false;
|
||||
};
|
||||
let ExprKind::Binary(op, lhs, rhs) = parent_expr.kind else {
|
||||
|
||||
@@ -301,7 +301,7 @@ fn check_fn(
|
||||
}
|
||||
|
||||
// Exclude non-inherent impls
|
||||
if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) {
|
||||
if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) {
|
||||
if matches!(
|
||||
item.kind,
|
||||
ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
|
||||
|
||||
@@ -289,7 +289,7 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>
|
||||
{
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
|
||||
let requires_semi = matches!(get_parent_node(cx.tcx, expr.hir_id), Some(Node::Stmt(_)));
|
||||
let requires_semi = matches!(get_parent_node(cx.tcx, expr.hir_id), Node::Stmt(_));
|
||||
let sugg = format!(
|
||||
"{receiver_str}{}?{}",
|
||||
if by_ref == ByRef::Yes { ".as_ref()" } else { "" },
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::rustc_lint::LintContext;
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||
use clippy_utils::get_parent_expr;
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::{get_parent_expr, get_parent_node};
|
||||
use hir::Param;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
@@ -200,11 +200,11 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
|
||||
hint = hint.asyncify();
|
||||
}
|
||||
|
||||
let is_in_fn_call_arg =
|
||||
clippy_utils::get_parent_node(cx.tcx, expr.hir_id).is_some_and(|x| match x {
|
||||
Node::Expr(expr) => matches!(expr.kind, hir::ExprKind::Call(_, _)),
|
||||
_ => false,
|
||||
});
|
||||
let is_in_fn_call_arg = if let Node::Expr(expr) = get_parent_node(cx.tcx, expr.hir_id) {
|
||||
matches!(expr.kind, hir::ExprKind::Call(_, _))
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
// avoid clippy::double_parens
|
||||
if !is_in_fn_call_arg {
|
||||
|
||||
@@ -101,7 +101,7 @@ fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) {
|
||||
fn is_by_value_closure_capture(cx: &LateContext<'_>, redefinition: HirId, root_variable: HirId) -> bool {
|
||||
let closure_def_id = cx.tcx.hir().enclosing_body_owner(redefinition);
|
||||
|
||||
cx.tcx.is_closure_or_coroutine(closure_def_id.to_def_id())
|
||||
cx.tcx.is_closure_like(closure_def_id.to_def_id())
|
||||
&& cx.tcx.closure_captures(closure_def_id).iter().any(|c| {
|
||||
matches!(c.info.capture_kind, UpvarCapture::ByValue)
|
||||
&& matches!(c.place.base, PlaceBase::Upvar(upvar) if upvar.var_path.hir_id == root_variable)
|
||||
|
||||
@@ -200,7 +200,7 @@ fn check_local<'tcx>(&mut self, cx: &LateContext<'tcx>, local: &'tcx rustc_hir::
|
||||
span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation");
|
||||
}
|
||||
},
|
||||
LitKind::Err => (),
|
||||
LitKind::Err(_) => (),
|
||||
LitKind::ByteStr(..) => {
|
||||
// We only lint if the type annotation is an array type (e.g. &[u8; 4]).
|
||||
// If instead it is a slice (e.g. &[u8]) it may not be redundant, so we
|
||||
|
||||
@@ -47,7 +47,6 @@ struct ExistingName {
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
|
||||
#[expect(clippy::too_many_lines)]
|
||||
fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
|
||||
let mut map = FxHashMap::<Res, ExistingName>::default();
|
||||
|
||||
@@ -75,24 +74,23 @@ fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
|
||||
|
||||
match of_trait {
|
||||
Some(trait_ref) => {
|
||||
let mut methods_in_trait: BTreeSet<Symbol> =
|
||||
if let Some(Node::TraitRef(TraitRef { path, .. })) =
|
||||
cx.tcx.opt_hir_node(trait_ref.hir_ref_id)
|
||||
&& let Res::Def(DefKind::Trait, did) = path.res
|
||||
{
|
||||
// FIXME: if
|
||||
// `rustc_middle::ty::assoc::AssocItems::items` is public,
|
||||
// we can iterate its keys instead of `in_definition_order`,
|
||||
// which's more efficient
|
||||
cx.tcx
|
||||
.associated_items(did)
|
||||
.in_definition_order()
|
||||
.filter(|assoc_item| matches!(assoc_item.kind, AssocKind::Fn))
|
||||
.map(|assoc_item| assoc_item.name)
|
||||
.collect()
|
||||
} else {
|
||||
BTreeSet::new()
|
||||
};
|
||||
let mut methods_in_trait: BTreeSet<Symbol> = if let Node::TraitRef(TraitRef { path, .. }) =
|
||||
cx.tcx.hir_node(trait_ref.hir_ref_id)
|
||||
&& let Res::Def(DefKind::Trait, did) = path.res
|
||||
{
|
||||
// FIXME: if
|
||||
// `rustc_middle::ty::assoc::AssocItems::items` is public,
|
||||
// we can iterate its keys instead of `in_definition_order`,
|
||||
// which's more efficient
|
||||
cx.tcx
|
||||
.associated_items(did)
|
||||
.in_definition_order()
|
||||
.filter(|assoc_item| matches!(assoc_item.kind, AssocKind::Fn))
|
||||
.map(|assoc_item| assoc_item.name)
|
||||
.collect()
|
||||
} else {
|
||||
BTreeSet::new()
|
||||
};
|
||||
|
||||
let mut check_trait_method = |method_name: Symbol, trait_method_span: Span| {
|
||||
if let Some((impl_span, hir_id)) = existing_name.impl_methods.get(&method_name) {
|
||||
|
||||
@@ -73,7 +73,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<
|
||||
if let Some(self_def) = self_ty.ty_adt_def()
|
||||
&& let Some(self_local_did) = self_def.did().as_local()
|
||||
&& let self_id = cx.tcx.local_def_id_to_hir_id(self_local_did)
|
||||
&& let Some(Node::Item(x)) = cx.tcx.opt_hir_node(self_id)
|
||||
&& let Node::Item(x) = cx.tcx.hir_node(self_id)
|
||||
&& let type_name = x.ident.name.as_str().to_lowercase()
|
||||
&& (impl_item.ident.name.as_str() == type_name
|
||||
|| impl_item.ident.name.as_str().replace('_', "") == type_name)
|
||||
|
||||
@@ -51,11 +51,11 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
{
|
||||
let ctxt = expr.span.ctxt();
|
||||
let span = match get_parent_node(cx.tcx, expr.hir_id) {
|
||||
Some(Node::Block(&Block {
|
||||
Node::Block(&Block {
|
||||
rules: BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided),
|
||||
span,
|
||||
..
|
||||
})) if span.ctxt() == ctxt && !is_expr_unsafe(cx, self_arg) => span,
|
||||
}) if span.ctxt() == ctxt && !is_expr_unsafe(cx, self_arg) => span,
|
||||
_ => expr.span,
|
||||
};
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ pub(super) fn check<'tcx>(
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
if let Node::Expr(parent) = cx.tcx.hir().get_parent(e.hir_id)
|
||||
if let Node::Expr(parent) = cx.tcx.parent_hir_node(e.hir_id)
|
||||
&& parent.precedence().order() > ExprPrecedence::Cast.order()
|
||||
{
|
||||
sugg = format!("({sugg})");
|
||||
|
||||
@@ -153,13 +153,7 @@ fn all_bindings_are_for_conv<'tcx>(
|
||||
let Some(locals) = locals.iter().map(|e| path_to_local(e)).collect::<Option<Vec<_>>>() else {
|
||||
return false;
|
||||
};
|
||||
let Some(local_parents) = locals
|
||||
.iter()
|
||||
.map(|&l| cx.tcx.hir().find_parent(l))
|
||||
.collect::<Option<Vec<_>>>()
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
let local_parents = locals.iter().map(|l| cx.tcx.parent_hir_node(*l)).collect::<Vec<_>>();
|
||||
|
||||
local_parents
|
||||
.iter()
|
||||
|
||||
@@ -340,47 +340,43 @@ fn block_parents_have_safety_comment(
|
||||
cx: &LateContext<'_>,
|
||||
id: hir::HirId,
|
||||
) -> bool {
|
||||
if let Some(node) = get_parent_node(cx.tcx, id) {
|
||||
let (span, hir_id) = match node {
|
||||
Node::Expr(expr) => match get_parent_node(cx.tcx, expr.hir_id) {
|
||||
Some(Node::Local(hir::Local { span, hir_id, .. })) => (*span, *hir_id),
|
||||
Some(Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Const(..) | ItemKind::Static(..),
|
||||
span,
|
||||
owner_id,
|
||||
..
|
||||
})) => (*span, cx.tcx.local_def_id_to_hir_id(owner_id.def_id)),
|
||||
_ => {
|
||||
if is_branchy(expr) {
|
||||
return false;
|
||||
}
|
||||
(expr.span, expr.hir_id)
|
||||
},
|
||||
},
|
||||
Node::Stmt(hir::Stmt {
|
||||
kind:
|
||||
hir::StmtKind::Local(hir::Local { span, hir_id, .. })
|
||||
| hir::StmtKind::Expr(hir::Expr { span, hir_id, .. })
|
||||
| hir::StmtKind::Semi(hir::Expr { span, hir_id, .. }),
|
||||
..
|
||||
})
|
||||
| Node::Local(hir::Local { span, hir_id, .. }) => (*span, *hir_id),
|
||||
let (span, hir_id) = match get_parent_node(cx.tcx, id) {
|
||||
Node::Expr(expr) => match get_parent_node(cx.tcx, expr.hir_id) {
|
||||
Node::Local(hir::Local { span, hir_id, .. }) => (*span, *hir_id),
|
||||
Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Const(..) | ItemKind::Static(..),
|
||||
span,
|
||||
owner_id,
|
||||
..
|
||||
}) => (*span, cx.tcx.local_def_id_to_hir_id(owner_id.def_id)),
|
||||
_ => return false,
|
||||
};
|
||||
// if unsafe block is part of a let/const/static statement,
|
||||
// and accept_comment_above_statement is set to true
|
||||
// we accept the safety comment in the line the precedes this statement.
|
||||
accept_comment_above_statement
|
||||
&& span_with_attrs_has_safety_comment(cx, span, hir_id, accept_comment_above_attributes)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
_ => {
|
||||
if is_branchy(expr) {
|
||||
return false;
|
||||
}
|
||||
(expr.span, expr.hir_id)
|
||||
},
|
||||
},
|
||||
Node::Stmt(hir::Stmt {
|
||||
kind:
|
||||
hir::StmtKind::Local(hir::Local { span, hir_id, .. })
|
||||
| hir::StmtKind::Expr(hir::Expr { span, hir_id, .. })
|
||||
| hir::StmtKind::Semi(hir::Expr { span, hir_id, .. }),
|
||||
..
|
||||
})
|
||||
| Node::Local(hir::Local { span, hir_id, .. }) => (*span, *hir_id),
|
||||
Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Const(..) | ItemKind::Static(..),
|
||||
span,
|
||||
owner_id,
|
||||
..
|
||||
}) => (*span, cx.tcx.local_def_id_to_hir_id(owner_id.def_id)),
|
||||
_ => return false,
|
||||
};
|
||||
// if unsafe block is part of a let/const/static statement,
|
||||
// and accept_comment_above_statement is set to true
|
||||
// we accept the safety comment in the line the precedes this statement.
|
||||
accept_comment_above_statement
|
||||
&& span_with_attrs_has_safety_comment(cx, span, hir_id, accept_comment_above_attributes)
|
||||
}
|
||||
|
||||
/// Extends `span` to also include its attributes, then checks if that span has a safety comment.
|
||||
@@ -449,53 +445,49 @@ fn item_has_safety_comment(cx: &LateContext<'_>, item: &hir::Item<'_>) -> HasSaf
|
||||
if item.span.ctxt() != SyntaxContext::root() {
|
||||
return HasSafetyComment::No;
|
||||
}
|
||||
if let Some(parent_node) = get_parent_node(cx.tcx, item.hir_id()) {
|
||||
let comment_start = match parent_node {
|
||||
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 {
|
||||
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.
|
||||
return HasSafetyComment::Maybe;
|
||||
}
|
||||
},
|
||||
Node::Stmt(stmt) => {
|
||||
if let Some(Node::Block(block)) = get_parent_node(cx.tcx, stmt.hir_id) {
|
||||
walk_span_to_context(block.span, SyntaxContext::root()).map(Span::lo)
|
||||
} else {
|
||||
// Problem getting the parent node. Pretend a comment was found.
|
||||
return HasSafetyComment::Maybe;
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
let comment_start = match get_parent_node(cx.tcx, 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 {
|
||||
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.
|
||||
return HasSafetyComment::Maybe;
|
||||
},
|
||||
};
|
||||
|
||||
let source_map = cx.sess().source_map();
|
||||
if let Some(comment_start) = comment_start
|
||||
&& let Ok(unsafe_line) = source_map.lookup_line(item.span.lo())
|
||||
&& let Ok(comment_start_line) = source_map.lookup_line(comment_start)
|
||||
&& Lrc::ptr_eq(&unsafe_line.sf, &comment_start_line.sf)
|
||||
&& let Some(src) = unsafe_line.sf.src.as_deref()
|
||||
{
|
||||
return if comment_start_line.line >= unsafe_line.line {
|
||||
HasSafetyComment::No
|
||||
}
|
||||
},
|
||||
Node::Stmt(stmt) => {
|
||||
if let Node::Block(block) = get_parent_node(cx.tcx, stmt.hir_id) {
|
||||
walk_span_to_context(block.span, SyntaxContext::root()).map(Span::lo)
|
||||
} else {
|
||||
match text_has_safety_comment(
|
||||
src,
|
||||
&unsafe_line.sf.lines()[comment_start_line.line + 1..=unsafe_line.line],
|
||||
unsafe_line.sf.start_pos,
|
||||
) {
|
||||
Some(b) => HasSafetyComment::Yes(b),
|
||||
None => HasSafetyComment::No,
|
||||
}
|
||||
};
|
||||
}
|
||||
// Problem getting the parent node. Pretend a comment was found.
|
||||
return HasSafetyComment::Maybe;
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
// Doesn't support impls in this position. Pretend a comment was found.
|
||||
return HasSafetyComment::Maybe;
|
||||
},
|
||||
};
|
||||
|
||||
let source_map = cx.sess().source_map();
|
||||
if let Some(comment_start) = comment_start
|
||||
&& let Ok(unsafe_line) = source_map.lookup_line(item.span.lo())
|
||||
&& let Ok(comment_start_line) = source_map.lookup_line(comment_start)
|
||||
&& Lrc::ptr_eq(&unsafe_line.sf, &comment_start_line.sf)
|
||||
&& let Some(src) = unsafe_line.sf.src.as_deref()
|
||||
{
|
||||
return if comment_start_line.line >= unsafe_line.line {
|
||||
HasSafetyComment::No
|
||||
} else {
|
||||
match text_has_safety_comment(
|
||||
src,
|
||||
&unsafe_line.sf.lines()[comment_start_line.line + 1..=unsafe_line.line],
|
||||
unsafe_line.sf.start_pos,
|
||||
) {
|
||||
Some(b) => HasSafetyComment::Yes(b),
|
||||
None => HasSafetyComment::No,
|
||||
}
|
||||
};
|
||||
}
|
||||
HasSafetyComment::Maybe
|
||||
}
|
||||
@@ -512,32 +504,30 @@ fn stmt_has_safety_comment(cx: &LateContext<'_>, span: Span, hir_id: HirId) -> H
|
||||
return HasSafetyComment::No;
|
||||
}
|
||||
|
||||
if let Some(parent_node) = get_parent_node(cx.tcx, hir_id) {
|
||||
let comment_start = match parent_node {
|
||||
Node::Block(block) => walk_span_to_context(block.span, SyntaxContext::root()).map(Span::lo),
|
||||
_ => return HasSafetyComment::Maybe,
|
||||
};
|
||||
let comment_start = match get_parent_node(cx.tcx, hir_id) {
|
||||
Node::Block(block) => walk_span_to_context(block.span, SyntaxContext::root()).map(Span::lo),
|
||||
_ => return HasSafetyComment::Maybe,
|
||||
};
|
||||
|
||||
let source_map = cx.sess().source_map();
|
||||
if let Some(comment_start) = comment_start
|
||||
&& let Ok(unsafe_line) = source_map.lookup_line(span.lo())
|
||||
&& let Ok(comment_start_line) = source_map.lookup_line(comment_start)
|
||||
&& Lrc::ptr_eq(&unsafe_line.sf, &comment_start_line.sf)
|
||||
&& let Some(src) = unsafe_line.sf.src.as_deref()
|
||||
{
|
||||
return if comment_start_line.line >= unsafe_line.line {
|
||||
HasSafetyComment::No
|
||||
} else {
|
||||
match text_has_safety_comment(
|
||||
src,
|
||||
&unsafe_line.sf.lines()[comment_start_line.line + 1..=unsafe_line.line],
|
||||
unsafe_line.sf.start_pos,
|
||||
) {
|
||||
Some(b) => HasSafetyComment::Yes(b),
|
||||
None => HasSafetyComment::No,
|
||||
}
|
||||
};
|
||||
}
|
||||
let source_map = cx.sess().source_map();
|
||||
if let Some(comment_start) = comment_start
|
||||
&& let Ok(unsafe_line) = source_map.lookup_line(span.lo())
|
||||
&& let Ok(comment_start_line) = source_map.lookup_line(comment_start)
|
||||
&& Lrc::ptr_eq(&unsafe_line.sf, &comment_start_line.sf)
|
||||
&& let Some(src) = unsafe_line.sf.src.as_deref()
|
||||
{
|
||||
return if comment_start_line.line >= unsafe_line.line {
|
||||
HasSafetyComment::No
|
||||
} else {
|
||||
match text_has_safety_comment(
|
||||
src,
|
||||
&unsafe_line.sf.lines()[comment_start_line.line + 1..=unsafe_line.line],
|
||||
unsafe_line.sf.start_pos,
|
||||
) {
|
||||
Some(b) => HasSafetyComment::Yes(b),
|
||||
None => HasSafetyComment::No,
|
||||
}
|
||||
};
|
||||
}
|
||||
HasSafetyComment::Maybe
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ fn expr_needs_inferred_result<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -
|
||||
return false;
|
||||
}
|
||||
while let Some(id) = locals_to_check.pop() {
|
||||
if let Some(Node::Local(l)) = get_parent_node(cx.tcx, id) {
|
||||
if let Node::Local(l) = get_parent_node(cx.tcx, id) {
|
||||
if !l.ty.map_or(true, |ty| matches!(ty.kind, TyKind::Infer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -19,9 +19,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||
if is_questionmark_desugar_marked_call(expr) {
|
||||
return;
|
||||
}
|
||||
let map = &cx.tcx.hir();
|
||||
let opt_parent_node = map.find_parent(expr.hir_id);
|
||||
if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node
|
||||
if let hir::Node::Expr(parent_expr) = cx.tcx.parent_hir_node(expr.hir_id)
|
||||
&& is_questionmark_desugar_marked_call(parent_expr)
|
||||
{
|
||||
return;
|
||||
@@ -183,8 +181,8 @@ fn fmt_stmts_and_call(
|
||||
|
||||
let mut stmts_and_call_snippet = stmts_and_call.join(&format!("{}{}", ";\n", " ".repeat(call_expr_indent)));
|
||||
// expr is not in a block statement or result expression position, wrap in a block
|
||||
let parent_node = cx.tcx.hir().find_parent(call_expr.hir_id);
|
||||
if !matches!(parent_node, Some(Node::Block(_))) && !matches!(parent_node, Some(Node::Stmt(_))) {
|
||||
let parent_node = cx.tcx.parent_hir_node(call_expr.hir_id);
|
||||
if !matches!(parent_node, Node::Block(_)) && !matches!(parent_node, Node::Stmt(_)) {
|
||||
let block_indent = call_expr_indent + 4;
|
||||
stmts_and_call_snippet =
|
||||
reindent_multiline(stmts_and_call_snippet.into(), true, Some(block_indent)).into_owned();
|
||||
|
||||
@@ -116,7 +116,7 @@ fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) {
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::ImplItem<'_>) {
|
||||
// Ignore implementations of traits, because the lint should be on the
|
||||
// trait, not on the implementation of it.
|
||||
let Node::Item(parent) = cx.tcx.hir().get_parent(item.hir_id()) else {
|
||||
let Node::Item(parent) = cx.tcx.parent_hir_node(item.hir_id()) else {
|
||||
return;
|
||||
};
|
||||
let ItemKind::Impl(parent) = parent.kind else { return };
|
||||
|
||||
@@ -92,7 +92,7 @@ fn check_fn(
|
||||
|
||||
// Abort if the method is implementing a trait or of it a trait method.
|
||||
let hir_id = cx.tcx.local_def_id_to_hir_id(def_id);
|
||||
if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) {
|
||||
if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) {
|
||||
if matches!(
|
||||
item.kind,
|
||||
ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..)
|
||||
|
||||
@@ -156,7 +156,7 @@ fn is_node_func_call(node: Node<'_>, expected_receiver: Span) -> bool {
|
||||
&& let Some(local_def_id) = def_id.as_local()
|
||||
&& cx.tcx.def_kind(def_id) == DefKind::Fn
|
||||
&& cx.tcx.asyncness(def_id).is_async()
|
||||
&& !is_node_func_call(cx.tcx.hir().get_parent(hir_id), path.span)
|
||||
&& !is_node_func_call(cx.tcx.parent_hir_node(hir_id), path.span)
|
||||
{
|
||||
self.async_fns_as_value.insert(local_def_id);
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ struct MutationVisitor<'tcx> {
|
||||
/// (i.e. the `x` in `x.as_mut()`), and that is the reason for why we care about its parent
|
||||
/// expression: that will be where the actual method call is.
|
||||
fn is_option_as_mut_use(tcx: TyCtxt<'_>, expr_id: HirId) -> bool {
|
||||
if let Node::Expr(mutating_expr) = tcx.hir().get_parent(expr_id)
|
||||
if let Node::Expr(mutating_expr) = tcx.parent_hir_node(expr_id)
|
||||
&& let ExprKind::MethodCall(path, ..) = mutating_expr.kind
|
||||
{
|
||||
path.ident.name.as_str() == "as_mut"
|
||||
|
||||
@@ -86,7 +86,6 @@ fn into_iter_bound<'tcx>(
|
||||
param_index: u32,
|
||||
node_args: GenericArgsRef<'tcx>,
|
||||
) -> Option<Span> {
|
||||
let param_env = cx.tcx.param_env(fn_did);
|
||||
let mut into_iter_span = None;
|
||||
|
||||
for (pred, span) in cx.tcx.explicit_predicates_of(fn_did).predicates {
|
||||
@@ -111,7 +110,7 @@ fn into_iter_bound<'tcx>(
|
||||
}));
|
||||
|
||||
let predicate = EarlyBinder::bind(tr).instantiate(cx.tcx, args);
|
||||
let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), param_env, predicate);
|
||||
let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
|
||||
if !cx
|
||||
.tcx
|
||||
.infer_ctxt()
|
||||
|
||||
@@ -279,7 +279,7 @@ macro_rules! kind {
|
||||
match lit.value.node {
|
||||
LitKind::Bool(val) => kind!("Bool({val:?})"),
|
||||
LitKind::Char(c) => kind!("Char({c:?})"),
|
||||
LitKind::Err => kind!("Err"),
|
||||
LitKind::Err(_) => kind!("Err"),
|
||||
LitKind::Byte(b) => kind!("Byte({b})"),
|
||||
LitKind::Int(i, suffix) => {
|
||||
let int_ty = match suffix {
|
||||
|
||||
@@ -1005,11 +1005,9 @@ fn get_parent_local<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) -
|
||||
}
|
||||
|
||||
fn get_parent_local_hir_id<'hir>(cx: &LateContext<'hir>, hir_id: hir::HirId) -> Option<&'hir hir::Local<'hir>> {
|
||||
let map = cx.tcx.hir();
|
||||
|
||||
match map.find_parent(hir_id) {
|
||||
Some(hir::Node::Local(local)) => Some(local),
|
||||
Some(hir::Node::Pat(pattern)) => get_parent_local_hir_id(cx, pattern.hir_id),
|
||||
match cx.tcx.parent_hir_node(hir_id) {
|
||||
hir::Node::Local(local) => Some(local),
|
||||
hir::Node::Pat(pattern) => get_parent_local_hir_id(cx, pattern.hir_id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,8 +217,7 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Ve
|
||||
match peel_hir_expr_refs(expr).0.kind {
|
||||
ExprKind::Path(ref qpath) => match cx.qpath_res(qpath, expr.hir_id) {
|
||||
Res::Local(hir_id) => {
|
||||
let parent_id = cx.tcx.hir().parent_id(hir_id);
|
||||
if let Node::Local(Local { init: Some(init), .. }) = cx.tcx.hir_node(parent_id) {
|
||||
if let Node::Local(Local { init: Some(init), .. }) = cx.tcx.parent_hir_node(hir_id) {
|
||||
path_to_matched_type(cx, init)
|
||||
} else {
|
||||
None
|
||||
|
||||
@@ -74,7 +74,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if let Some(vec_args) = higher::VecArgs::hir(cx, expr.peel_borrows()) {
|
||||
// search for `let foo = vec![_]` expressions where all uses of `foo`
|
||||
// adjust to slices or call a method that exist on slices (e.g. len)
|
||||
if let Node::Local(local) = cx.tcx.hir().get_parent(expr.hir_id)
|
||||
if let Node::Local(local) = cx.tcx.parent_hir_node(expr.hir_id)
|
||||
// for now ignore locals with type annotations.
|
||||
// this is to avoid compile errors when doing the suggestion here: let _: Vec<_> = vec![..];
|
||||
&& local.ty.is_none()
|
||||
@@ -103,7 +103,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
}
|
||||
// if the local pattern has a specified type, do not lint.
|
||||
else if let Some(_) = higher::VecArgs::hir(cx, expr)
|
||||
&& let Node::Local(local) = cx.tcx.hir().get_parent(expr.hir_id)
|
||||
&& let Node::Local(local) = cx.tcx.parent_hir_node(expr.hir_id)
|
||||
&& local.ty.is_some()
|
||||
{
|
||||
let span = expr.span.ctxt().outer_expn_data().call_site;
|
||||
|
||||
@@ -690,7 +690,9 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool {
|
||||
match (&l.kind, &r.kind) {
|
||||
(Paren(l), _) => eq_ty(l, r),
|
||||
(_, Paren(r)) => eq_ty(l, r),
|
||||
(Never, Never) | (Infer, Infer) | (ImplicitSelf, ImplicitSelf) | (Err, Err) | (CVarArgs, CVarArgs) => true,
|
||||
(Never, Never) | (Infer, Infer) | (ImplicitSelf, ImplicitSelf) | (Err(_), Err(_)) | (CVarArgs, CVarArgs) => {
|
||||
true
|
||||
},
|
||||
(Slice(l), Slice(r)) => eq_ty(l, r),
|
||||
(Array(le, ls), Array(re, rs)) => eq_ty(le, re) && eq_expr(&ls.value, &rs.value),
|
||||
(Ptr(l), Ptr(r)) => l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty),
|
||||
|
||||
@@ -286,7 +286,7 @@ pub fn lit_to_mir_constant<'tcx>(lit: &LitKind, ty: Option<Ty<'tcx>>) -> Constan
|
||||
_ => bug!(),
|
||||
},
|
||||
LitKind::Bool(b) => Constant::Bool(b),
|
||||
LitKind::Err => Constant::Err,
|
||||
LitKind::Err(_) => Constant::Err,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
//! Thank you!
|
||||
//! ~The `INTERNAL_METADATA_COLLECTOR` lint
|
||||
|
||||
use rustc_errors::{Applicability, Diagnostic, MultiSpan};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder, MultiSpan};
|
||||
use rustc_hir::HirId;
|
||||
use rustc_lint::{LateContext, Lint, LintContext};
|
||||
use rustc_span::Span;
|
||||
use std::env;
|
||||
|
||||
fn docs_link(diag: &mut Diagnostic, lint: &'static Lint) {
|
||||
fn docs_link(diag: &mut DiagnosticBuilder<'_, ()>, lint: &'static Lint) {
|
||||
if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() {
|
||||
if let Some(lint) = lint.name_lower().strip_prefix("clippy::") {
|
||||
diag.help(format!(
|
||||
@@ -143,7 +143,7 @@ pub fn span_lint_and_then<C, S, F>(cx: &C, lint: &'static Lint, sp: S, msg: &str
|
||||
where
|
||||
C: LintContext,
|
||||
S: Into<MultiSpan>,
|
||||
F: FnOnce(&mut Diagnostic),
|
||||
F: FnOnce(&mut DiagnosticBuilder<'_, ()>),
|
||||
{
|
||||
#[expect(clippy::disallowed_methods)]
|
||||
cx.span_lint(lint, sp, msg.to_string(), |diag| {
|
||||
@@ -165,7 +165,7 @@ pub fn span_lint_hir_and_then(
|
||||
hir_id: HirId,
|
||||
sp: impl Into<MultiSpan>,
|
||||
msg: &str,
|
||||
f: impl FnOnce(&mut Diagnostic),
|
||||
f: impl FnOnce(&mut DiagnosticBuilder<'_, ()>),
|
||||
) {
|
||||
#[expect(clippy::disallowed_methods)]
|
||||
cx.tcx.node_span_lint(lint, hir_id, sp, msg.to_string(), |diag| {
|
||||
@@ -214,7 +214,7 @@ pub fn span_lint_and_sugg<T: LintContext>(
|
||||
/// appear once per
|
||||
/// replacement. In human-readable format though, it only appears once before
|
||||
/// the whole suggestion.
|
||||
pub fn multispan_sugg<I>(diag: &mut Diagnostic, help_msg: &str, sugg: I)
|
||||
pub fn multispan_sugg<I>(diag: &mut DiagnosticBuilder<'_, ()>, help_msg: &str, sugg: I)
|
||||
where
|
||||
I: IntoIterator<Item = (Span, String)>,
|
||||
{
|
||||
@@ -227,7 +227,7 @@ pub fn multispan_sugg<I>(diag: &mut Diagnostic, help_msg: &str, sugg: I)
|
||||
/// multiple spans. This is tracked in issue [rustfix#141](https://github.com/rust-lang/rustfix/issues/141).
|
||||
/// Suggestions with multiple spans will be silently ignored.
|
||||
pub fn multispan_sugg_with_applicability<I>(
|
||||
diag: &mut Diagnostic,
|
||||
diag: &mut DiagnosticBuilder<'_, ()>,
|
||||
help_msg: &str,
|
||||
applicability: Applicability,
|
||||
sugg: I,
|
||||
|
||||
@@ -513,6 +513,7 @@ pub fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool {
|
||||
(TyKind::Path(l), TyKind::Path(r)) => self.eq_qpath(l, r),
|
||||
(&TyKind::Tup(l), &TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)),
|
||||
(&TyKind::Infer, &TyKind::Infer) => true,
|
||||
(TyKind::AnonAdt(l_item_id), TyKind::AnonAdt(r_item_id)) => l_item_id == r_item_id,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@@ -1106,7 +1107,7 @@ pub fn hash_tykind(&mut self, ty: &TyKind<'_>) {
|
||||
TyKind::Typeof(anon_const) => {
|
||||
self.hash_body(anon_const.body);
|
||||
},
|
||||
TyKind::Err(_) | TyKind::Infer | TyKind::Never | TyKind::InferDelegation(..) => {},
|
||||
TyKind::Err(_) | TyKind::Infer | TyKind::Never | TyKind::InferDelegation(..) | TyKind::AnonAdt(_) => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-15
@@ -9,7 +9,13 @@
|
||||
#![feature(assert_matches)]
|
||||
#![recursion_limit = "512"]
|
||||
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
||||
#![allow(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)]
|
||||
#![allow(
|
||||
clippy::missing_errors_doc,
|
||||
clippy::missing_panics_doc,
|
||||
clippy::must_use_candidate,
|
||||
rustc::diagnostic_outside_of_impl,
|
||||
rustc::untranslatable_diagnostic
|
||||
)]
|
||||
// warn on the same lints as `clippy_lints`
|
||||
#![warn(trivial_casts, trivial_numeric_casts)]
|
||||
// warn on lints, that are included in `rust-lang/rust`s bootstrap
|
||||
@@ -176,11 +182,9 @@ pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr
|
||||
/// Note: If you have an expression that references a binding `x`, use `path_to_local` to get the
|
||||
/// canonical binding `HirId`.
|
||||
pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> {
|
||||
let hir = cx.tcx.hir();
|
||||
if let Some(Node::Pat(pat)) = cx.tcx.opt_hir_node(hir_id)
|
||||
if let Node::Pat(pat) = cx.tcx.hir_node(hir_id)
|
||||
&& matches!(pat.kind, PatKind::Binding(BindingAnnotation::NONE, ..))
|
||||
&& let parent = hir.parent_id(hir_id)
|
||||
&& let Some(Node::Local(local)) = cx.tcx.opt_hir_node(parent)
|
||||
&& let Node::Local(local) = cx.tcx.parent_hir_node(hir_id)
|
||||
{
|
||||
return local.init;
|
||||
}
|
||||
@@ -327,7 +331,7 @@ pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol)
|
||||
/// Checks if the `def_id` belongs to a function that is part of a trait impl.
|
||||
pub fn is_def_id_trait_method(cx: &LateContext<'_>, def_id: LocalDefId) -> bool {
|
||||
if let Some(hir_id) = cx.tcx.opt_local_def_id_to_hir_id(def_id)
|
||||
&& let Node::Item(item) = cx.tcx.hir().get_parent(hir_id)
|
||||
&& let Node::Item(item) = cx.tcx.parent_hir_node(hir_id)
|
||||
&& let ItemKind::Impl(imp) = item.kind
|
||||
{
|
||||
imp.of_trait.is_some()
|
||||
@@ -1304,8 +1308,8 @@ pub fn contains_return<'tcx>(expr: impl Visitable<'tcx>) -> bool {
|
||||
}
|
||||
|
||||
/// Gets the parent node, if any.
|
||||
pub fn get_parent_node(tcx: TyCtxt<'_>, id: HirId) -> Option<Node<'_>> {
|
||||
tcx.hir().find_parent(id)
|
||||
pub fn get_parent_node(tcx: TyCtxt<'_>, id: HirId) -> Node<'_> {
|
||||
tcx.parent_hir_node(id)
|
||||
}
|
||||
|
||||
/// Gets the parent expression, if any –- this is useful to constrain a lint.
|
||||
@@ -1317,7 +1321,7 @@ pub fn get_parent_expr<'tcx>(cx: &LateContext<'tcx>, e: &Expr<'_>) -> Option<&'t
|
||||
/// constraint lints
|
||||
pub fn get_parent_expr_for_hir<'tcx>(cx: &LateContext<'tcx>, hir_id: hir::HirId) -> Option<&'tcx Expr<'tcx>> {
|
||||
match get_parent_node(cx.tcx, hir_id) {
|
||||
Some(Node::Expr(parent)) => Some(parent),
|
||||
Node::Expr(parent) => Some(parent),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -1327,7 +1331,7 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio
|
||||
let map = &cx.tcx.hir();
|
||||
let enclosing_node = map
|
||||
.get_enclosing_scope(hir_id)
|
||||
.and_then(|enclosing_id| cx.tcx.opt_hir_node(enclosing_id));
|
||||
.map(|enclosing_id| cx.tcx.hir_node(enclosing_id));
|
||||
enclosing_node.and_then(|node| match node {
|
||||
Node::Block(block) => Some(block),
|
||||
Node::Item(&Item {
|
||||
@@ -2178,7 +2182,7 @@ pub fn is_expr_used_or_unified(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
|
||||
|
||||
/// Checks if the expression is the final expression returned from a block.
|
||||
pub fn is_expr_final_block_expr(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
|
||||
matches!(get_parent_node(tcx, expr.hir_id), Some(Node::Block(..)))
|
||||
matches!(get_parent_node(tcx, expr.hir_id), Node::Block(..))
|
||||
}
|
||||
|
||||
pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> {
|
||||
@@ -2221,7 +2225,7 @@ pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
|
||||
/// }
|
||||
/// ```
|
||||
pub fn is_trait_impl_item(cx: &LateContext<'_>, hir_id: HirId) -> bool {
|
||||
if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) {
|
||||
if let Node::Item(item) = cx.tcx.parent_hir_node(hir_id) {
|
||||
matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
|
||||
} else {
|
||||
false
|
||||
@@ -2669,10 +2673,10 @@ pub fn defined_ty(&self, cx: &LateContext<'tcx>) -> Option<DefinedTy<'tcx>> {
|
||||
)),
|
||||
Self::Return(id) => {
|
||||
let hir_id = cx.tcx.local_def_id_to_hir_id(id.def_id);
|
||||
if let Some(Node::Expr(Expr {
|
||||
if let Node::Expr(Expr {
|
||||
kind: ExprKind::Closure(c),
|
||||
..
|
||||
})) = cx.tcx.opt_hir_node(hir_id)
|
||||
}) = cx.tcx.hir_node(hir_id)
|
||||
{
|
||||
match c.fn_decl.output {
|
||||
FnRetTy::DefaultReturn(_) => None,
|
||||
@@ -2740,7 +2744,7 @@ pub fn expr_use_ctxt<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> Optio
|
||||
{
|
||||
adjustments = cx.typeck_results().expr_adjustments(e);
|
||||
}
|
||||
if !cx.tcx.hir().opt_span(parent_id).is_some_and(|x| x.ctxt() == ctxt) {
|
||||
if cx.tcx.hir().span(parent_id).ctxt() != ctxt {
|
||||
return ControlFlow::Break(());
|
||||
}
|
||||
if let Node::Expr(e) = parent {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
["rustc_lint_defs", "Applicability", "MaybeIncorrect"],
|
||||
["rustc_lint_defs", "Applicability", "MachineApplicable"],
|
||||
];
|
||||
pub const DIAGNOSTIC_BUILDER: [&str; 3] = ["rustc_errors", "diagnostic_builder", "DiagnosticBuilder"];
|
||||
pub const DIAGNOSTIC_BUILDER: [&str; 2] = ["rustc_errors", "DiagnosticBuilder"];
|
||||
pub const BINARYHEAP_ITER: [&str; 5] = ["alloc", "collections", "binary_heap", "BinaryHeap", "iter"];
|
||||
pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "contains_key"];
|
||||
pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"];
|
||||
|
||||
@@ -174,9 +174,8 @@ fn check_rvalue<'tcx>(
|
||||
))
|
||||
}
|
||||
},
|
||||
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_), _) | Rvalue::ShallowInitBox(_, _) => {
|
||||
Ok(())
|
||||
},
|
||||
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::DebugAssertions, _)
|
||||
| Rvalue::ShallowInitBox(_, _) => Ok(()),
|
||||
Rvalue::UnaryOp(_, operand) => {
|
||||
let ty = operand.ty(body, tcx);
|
||||
if ty.is_integral() || ty.is_bool() {
|
||||
@@ -335,7 +334,7 @@ fn check_terminator<'tcx>(
|
||||
// within const fns. `transmute` is allowed in all other const contexts.
|
||||
// This won't really scale to more intrinsics or functions. Let's allow const
|
||||
// transmutes in const fn before we add more hacks to this.
|
||||
if tcx.is_intrinsic(fn_def_id) && tcx.item_name(fn_def_id) == sym::transmute {
|
||||
if matches!(tcx.intrinsic(fn_def_id), Some(sym::transmute)) {
|
||||
return Err((
|
||||
span,
|
||||
"can only call `transmute` from const items, not `const fn`".into(),
|
||||
|
||||
@@ -683,7 +683,7 @@ fn indentation<T: LintContext>(cx: &T, span: Span) -> Option<String> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Convenience extension trait for `Diagnostic`.
|
||||
/// Convenience extension trait for `DiagnosticBuilder`.
|
||||
pub trait DiagnosticExt<T: LintContext> {
|
||||
/// Suggests to add an attribute to an item.
|
||||
///
|
||||
@@ -731,7 +731,7 @@ fn suggest_item_with_attr<D: Display + ?Sized>(
|
||||
fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str, applicability: Applicability);
|
||||
}
|
||||
|
||||
impl<T: LintContext> DiagnosticExt<T> for rustc_errors::Diagnostic {
|
||||
impl<T: LintContext> DiagnosticExt<T> for rustc_errors::DiagnosticBuilder<'_, ()> {
|
||||
fn suggest_item_with_attr<D: Display + ?Sized>(
|
||||
&mut self,
|
||||
cx: &T,
|
||||
|
||||
@@ -237,7 +237,7 @@ fn path_segment_certainty(
|
||||
},
|
||||
|
||||
// `get_parent` because `hir_id` refers to a `Pat`, and we're interested in the node containing the `Pat`.
|
||||
Res::Local(hir_id) => match cx.tcx.hir().get_parent(hir_id) {
|
||||
Res::Local(hir_id) => match cx.tcx.parent_hir_node(hir_id) {
|
||||
// An argument's type is always certain.
|
||||
Node::Param(..) => Certainty::Certain(None),
|
||||
// A local's type is certain if its type annotation is certain or it has an initializer whose
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2024-02-08"
|
||||
channel = "nightly-2024-02-22"
|
||||
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
||||
|
||||
+2
-1
@@ -1,3 +1,5 @@
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(lazy_cell)]
|
||||
@@ -26,7 +28,6 @@
|
||||
use std::ops::Deref;
|
||||
use std::path::Path;
|
||||
use std::process::exit;
|
||||
use std::string::ToString;
|
||||
|
||||
use anstream::println;
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ fn integration_test() {
|
||||
// the repo basically just contains a span_delayed_bug that forces rustc/clippy to panic:
|
||||
/*
|
||||
#![feature(rustc_attrs)]
|
||||
#[rustc_error(span_delayed_bug_from_inside_query)]
|
||||
#[rustc_error(delayed_bug_from_inside_query)]
|
||||
fn main() {}
|
||||
*/
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
|
||||
const ARR: [i32; 2] = [1, 2];
|
||||
const REF: &i32 = &ARR[idx()]; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
|
||||
const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
|
||||
//~^ ERROR: failed
|
||||
|
||||
const fn idx() -> usize {
|
||||
1
|
||||
@@ -35,9 +33,6 @@ fn main() {
|
||||
x[const { idx() }]; // Ok, should not produce stderr.
|
||||
x[const { idx4() }]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
|
||||
const { &ARR[idx()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
|
||||
const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
|
||||
//
|
||||
//~^^ ERROR: failed
|
||||
|
||||
let y = &x;
|
||||
y[0]; // Ok, referencing shouldn't affect this lint. See the issue 6021
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
error[E0080]: evaluation of `main::{constant#3}` failed
|
||||
--> tests/ui-toml/suppress_lint_in_const/test.rs:38:14
|
||||
|
|
||||
LL | const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
|
||||
| ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> tests/ui-toml/suppress_lint_in_const/test.rs:38:5
|
||||
|
|
||||
LL | const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: indexing may panic
|
||||
--> tests/ui-toml/suppress_lint_in_const/test.rs:29:5
|
||||
--> tests/ui-toml/suppress_lint_in_const/test.rs:27:5
|
||||
|
|
||||
LL | x[index];
|
||||
| ^^^^^^^^
|
||||
@@ -21,7 +9,7 @@ LL | x[index];
|
||||
= help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]`
|
||||
|
||||
error: indexing may panic
|
||||
--> tests/ui-toml/suppress_lint_in_const/test.rs:47:5
|
||||
--> tests/ui-toml/suppress_lint_in_const/test.rs:42:5
|
||||
|
|
||||
LL | v[0];
|
||||
| ^^^^
|
||||
@@ -29,7 +17,7 @@ LL | v[0];
|
||||
= help: consider using `.get(n)` or `.get_mut(n)` instead
|
||||
|
||||
error: indexing may panic
|
||||
--> tests/ui-toml/suppress_lint_in_const/test.rs:48:5
|
||||
--> tests/ui-toml/suppress_lint_in_const/test.rs:43:5
|
||||
|
|
||||
LL | v[10];
|
||||
| ^^^^^
|
||||
@@ -37,7 +25,7 @@ LL | v[10];
|
||||
= help: consider using `.get(n)` or `.get_mut(n)` instead
|
||||
|
||||
error: indexing may panic
|
||||
--> tests/ui-toml/suppress_lint_in_const/test.rs:49:5
|
||||
--> tests/ui-toml/suppress_lint_in_const/test.rs:44:5
|
||||
|
|
||||
LL | v[1 << 3];
|
||||
| ^^^^^^^^^
|
||||
@@ -45,7 +33,7 @@ LL | v[1 << 3];
|
||||
= help: consider using `.get(n)` or `.get_mut(n)` instead
|
||||
|
||||
error: indexing may panic
|
||||
--> tests/ui-toml/suppress_lint_in_const/test.rs:55:5
|
||||
--> tests/ui-toml/suppress_lint_in_const/test.rs:50:5
|
||||
|
|
||||
LL | v[N];
|
||||
| ^^^^
|
||||
@@ -53,19 +41,12 @@ LL | v[N];
|
||||
= help: consider using `.get(n)` or `.get_mut(n)` instead
|
||||
|
||||
error: indexing may panic
|
||||
--> tests/ui-toml/suppress_lint_in_const/test.rs:56:5
|
||||
--> tests/ui-toml/suppress_lint_in_const/test.rs:51:5
|
||||
|
|
||||
LL | v[M];
|
||||
| ^^^^
|
||||
|
|
||||
= help: consider using `.get(n)` or `.get_mut(n)` instead
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> tests/ui-toml/suppress_lint_in_const/test.rs:16:24
|
||||
|
|
||||
LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
|
||||
| ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
||||
@@ -31,7 +31,6 @@ LL | global_asm!("");
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: use AT&T x86 assembly syntax
|
||||
= note: this error originates in the macro `global_asm` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: Intel x86 assembly syntax used
|
||||
--> tests/ui/asm_syntax_x86.rs:22:5
|
||||
@@ -40,7 +39,6 @@ LL | global_asm!("", options());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: use AT&T x86 assembly syntax
|
||||
= note: this error originates in the macro `global_asm` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: AT&T x86 assembly syntax used
|
||||
--> tests/ui/asm_syntax_x86.rs:35:9
|
||||
@@ -67,7 +65,6 @@ LL | global_asm!("", options(att_syntax));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: use Intel x86 assembly syntax
|
||||
= note: this error originates in the macro `global_asm` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ LL | global_asm!("");
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: use AT&T x86 assembly syntax
|
||||
= note: this error originates in the macro `global_asm` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: Intel x86 assembly syntax used
|
||||
--> tests/ui/asm_syntax_x86.rs:22:5
|
||||
@@ -40,7 +39,6 @@ LL | global_asm!("", options());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: use AT&T x86 assembly syntax
|
||||
= note: this error originates in the macro `global_asm` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: AT&T x86 assembly syntax used
|
||||
--> tests/ui/asm_syntax_x86.rs:35:9
|
||||
@@ -67,7 +65,6 @@ LL | global_asm!("", options(att_syntax));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: use Intel x86 assembly syntax
|
||||
= note: this error originates in the macro `global_asm` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
const ARR: [i32; 2] = [1, 2];
|
||||
const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
|
||||
//~^ ERROR: indexing may panic
|
||||
const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
|
||||
//~^ ERROR: indexing may panic
|
||||
|
||||
const fn idx() -> usize {
|
||||
1
|
||||
|
||||
@@ -9,29 +9,20 @@ LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-re
|
||||
= note: `-D clippy::indexing-slicing` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]`
|
||||
|
||||
error: indexing may panic
|
||||
--> tests/ui/indexing_slicing_index.rs:16:24
|
||||
|
|
||||
LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: consider using `.get(n)` or `.get_mut(n)` instead
|
||||
= note: the suggestion might not be applicable in constant blocks
|
||||
|
||||
error[E0080]: evaluation of `main::{constant#3}` failed
|
||||
--> tests/ui/indexing_slicing_index.rs:48:14
|
||||
--> tests/ui/indexing_slicing_index.rs:46:14
|
||||
|
|
||||
LL | const { &ARR[idx4()] };
|
||||
| ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> tests/ui/indexing_slicing_index.rs:48:5
|
||||
--> tests/ui/indexing_slicing_index.rs:46:5
|
||||
|
|
||||
LL | const { &ARR[idx4()] };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: indexing may panic
|
||||
--> tests/ui/indexing_slicing_index.rs:29:5
|
||||
--> tests/ui/indexing_slicing_index.rs:27:5
|
||||
|
|
||||
LL | x[index];
|
||||
| ^^^^^^^^
|
||||
@@ -39,7 +30,7 @@ LL | x[index];
|
||||
= help: consider using `.get(n)` or `.get_mut(n)` instead
|
||||
|
||||
error: index is out of bounds
|
||||
--> tests/ui/indexing_slicing_index.rs:32:5
|
||||
--> tests/ui/indexing_slicing_index.rs:30:5
|
||||
|
|
||||
LL | x[4];
|
||||
| ^^^^
|
||||
@@ -48,13 +39,13 @@ LL | x[4];
|
||||
= help: to override `-D warnings` add `#[allow(clippy::out_of_bounds_indexing)]`
|
||||
|
||||
error: index is out of bounds
|
||||
--> tests/ui/indexing_slicing_index.rs:34:5
|
||||
--> tests/ui/indexing_slicing_index.rs:32:5
|
||||
|
|
||||
LL | x[1 << 3];
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: indexing may panic
|
||||
--> tests/ui/indexing_slicing_index.rs:45:14
|
||||
--> tests/ui/indexing_slicing_index.rs:43:14
|
||||
|
|
||||
LL | const { &ARR[idx()] };
|
||||
| ^^^^^^^^^^
|
||||
@@ -63,7 +54,7 @@ LL | const { &ARR[idx()] };
|
||||
= note: the suggestion might not be applicable in constant blocks
|
||||
|
||||
error: indexing may panic
|
||||
--> tests/ui/indexing_slicing_index.rs:48:14
|
||||
--> tests/ui/indexing_slicing_index.rs:46:14
|
||||
|
|
||||
LL | const { &ARR[idx4()] };
|
||||
| ^^^^^^^^^^^
|
||||
@@ -72,13 +63,13 @@ LL | const { &ARR[idx4()] };
|
||||
= note: the suggestion might not be applicable in constant blocks
|
||||
|
||||
error: index is out of bounds
|
||||
--> tests/ui/indexing_slicing_index.rs:55:5
|
||||
--> tests/ui/indexing_slicing_index.rs:53:5
|
||||
|
|
||||
LL | y[4];
|
||||
| ^^^^
|
||||
|
||||
error: indexing may panic
|
||||
--> tests/ui/indexing_slicing_index.rs:58:5
|
||||
--> tests/ui/indexing_slicing_index.rs:56:5
|
||||
|
|
||||
LL | v[0];
|
||||
| ^^^^
|
||||
@@ -86,7 +77,7 @@ LL | v[0];
|
||||
= help: consider using `.get(n)` or `.get_mut(n)` instead
|
||||
|
||||
error: indexing may panic
|
||||
--> tests/ui/indexing_slicing_index.rs:60:5
|
||||
--> tests/ui/indexing_slicing_index.rs:58:5
|
||||
|
|
||||
LL | v[10];
|
||||
| ^^^^^
|
||||
@@ -94,7 +85,7 @@ LL | v[10];
|
||||
= help: consider using `.get(n)` or `.get_mut(n)` instead
|
||||
|
||||
error: indexing may panic
|
||||
--> tests/ui/indexing_slicing_index.rs:62:5
|
||||
--> tests/ui/indexing_slicing_index.rs:60:5
|
||||
|
|
||||
LL | v[1 << 3];
|
||||
| ^^^^^^^^^
|
||||
@@ -102,13 +93,13 @@ LL | v[1 << 3];
|
||||
= help: consider using `.get(n)` or `.get_mut(n)` instead
|
||||
|
||||
error: index is out of bounds
|
||||
--> tests/ui/indexing_slicing_index.rs:70:5
|
||||
--> tests/ui/indexing_slicing_index.rs:68:5
|
||||
|
|
||||
LL | x[N];
|
||||
| ^^^^
|
||||
|
||||
error: indexing may panic
|
||||
--> tests/ui/indexing_slicing_index.rs:73:5
|
||||
--> tests/ui/indexing_slicing_index.rs:71:5
|
||||
|
|
||||
LL | v[N];
|
||||
| ^^^^
|
||||
@@ -116,7 +107,7 @@ LL | v[N];
|
||||
= help: consider using `.get(n)` or `.get_mut(n)` instead
|
||||
|
||||
error: indexing may panic
|
||||
--> tests/ui/indexing_slicing_index.rs:75:5
|
||||
--> tests/ui/indexing_slicing_index.rs:73:5
|
||||
|
|
||||
LL | v[M];
|
||||
| ^^^^
|
||||
@@ -124,17 +115,11 @@ LL | v[M];
|
||||
= help: consider using `.get(n)` or `.get_mut(n)` instead
|
||||
|
||||
error: index is out of bounds
|
||||
--> tests/ui/indexing_slicing_index.rs:79:13
|
||||
--> tests/ui/indexing_slicing_index.rs:77:13
|
||||
|
|
||||
LL | let _ = x[4];
|
||||
| ^^^^
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> tests/ui/indexing_slicing_index.rs:16:24
|
||||
|
|
||||
LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
|
||||
| ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
|
||||
|
||||
error: aborting due to 17 previous errors
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user