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

Rustup

r? `@ghost`

changelog: none
This commit is contained in:
bors 2024-01-25 18:06:39 +00:00
commit 66c29b973b
61 changed files with 265 additions and 180 deletions

View File

@ -2,6 +2,6 @@ avoid-breaking-exported-api = false
# use the various `span_lint_*` methods instead, which also add a link to the docs
disallowed-methods = [
"rustc_lint::context::LintContext::struct_span_lint",
"rustc_middle::ty::context::TyCtxt::struct_span_lint_hir"
"rustc_lint::context::LintContext::span_lint",
"rustc_middle::ty::context::TyCtxt::node_span_lint"
]

View File

@ -45,50 +45,72 @@ declare_lint_pass!(AsyncYieldsAsync => [ASYNC_YIELDS_ASYNC]);
impl<'tcx> LateLintPass<'tcx> for AsyncYieldsAsync {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
// For functions, with explicitly defined types, don't warn.
// XXXkhuey maybe we should?
if let ExprKind::Closure(Closure {
kind:
ClosureKind::Coroutine(CoroutineKind::Desugared(
CoroutineDesugaring::Async,
CoroutineSource::Block | CoroutineSource::Closure,
)),
let ExprKind::Closure(Closure {
kind: ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, kind)),
body: body_id,
..
}) = expr.kind
{
if let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() {
let typeck_results = cx.tcx.typeck_body(*body_id);
let body = cx.tcx.hir().body(*body_id);
let expr_ty = typeck_results.expr_ty(body.value);
else {
return;
};
if implements_trait(cx, expr_ty, future_trait_def_id, &[]) {
let return_expr_span = match &body.value.kind {
// XXXkhuey there has to be a better way.
ExprKind::Block(block, _) => block.expr.map(|e| e.span),
ExprKind::Path(QPath::Resolved(_, path)) => Some(path.span),
_ => None,
};
if let Some(return_expr_span) = return_expr_span {
span_lint_hir_and_then(
cx,
ASYNC_YIELDS_ASYNC,
body.value.hir_id,
let body_expr = match kind {
CoroutineSource::Fn => {
// For functions, with explicitly defined types, don't warn.
// XXXkhuey maybe we should?
return;
},
CoroutineSource::Block => cx.tcx.hir().body(*body_id).value,
CoroutineSource::Closure => {
// Like `async fn`, async closures are wrapped in an additional block
// to move all of the closure's arguments into the future.
let async_closure_body = cx.tcx.hir().body(*body_id).value;
let ExprKind::Block(block, _) = async_closure_body.kind else {
return;
};
let Some(block_expr) = block.expr else {
return;
};
let ExprKind::DropTemps(body_expr) = block_expr.kind else {
return;
};
body_expr
},
};
let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() else {
return;
};
let typeck_results = cx.tcx.typeck_body(*body_id);
let expr_ty = typeck_results.expr_ty(body_expr);
if implements_trait(cx, expr_ty, future_trait_def_id, &[]) {
let return_expr_span = match &body_expr.kind {
// XXXkhuey there has to be a better way.
ExprKind::Block(block, _) => block.expr.map(|e| e.span),
ExprKind::Path(QPath::Resolved(_, path)) => Some(path.span),
_ => None,
};
if let Some(return_expr_span) = return_expr_span {
span_lint_hir_and_then(
cx,
ASYNC_YIELDS_ASYNC,
body_expr.hir_id,
return_expr_span,
"an async construct yields a type which is itself awaitable",
|db| {
db.span_label(body_expr.span, "outer async construct");
db.span_label(return_expr_span, "awaitable value not awaited");
db.span_suggestion(
return_expr_span,
"an async construct yields a type which is itself awaitable",
|db| {
db.span_label(body.value.span, "outer async construct");
db.span_label(return_expr_span, "awaitable value not awaited");
db.span_suggestion(
return_expr_span,
"consider awaiting this value",
format!("{}.await", snippet(cx, return_expr_span, "..")),
Applicability::MaybeIncorrect,
);
},
"consider awaiting this value",
format!("{}.await", snippet(cx, return_expr_span, "..")),
Applicability::MaybeIncorrect,
);
}
}
},
);
}
}
}

View File

@ -107,7 +107,7 @@ pub(super) fn check<'tcx>(
&& let Some(src) = snippet_opt(cx, cast_expr.span)
&& cast_to.is_floating_point()
&& let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node)
&& let from_nbits = 128 - n.leading_zeros()
&& let from_nbits = 128 - n.get().leading_zeros()
&& let to_nbits = fp_ty_mantissa_nbits(cast_to)
&& from_nbits != 0
&& to_nbits != 0

View File

@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation {
/// (ZST fields having an arbitrary offset is completely inconsequential, and
/// if there is only one field left after ignoring ZST fields then the offset
/// of that field does not matter either.)
fn is_union_with_two_non_zst_fields(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
fn is_union_with_two_non_zst_fields<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool {
if let ItemKind::Union(..) = &item.kind
&& let ty::Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind()
{

View File

@ -830,6 +830,7 @@ impl TyCoercionStability {
| TyKind::Infer
| TyKind::Typeof(..)
| TyKind::TraitObject(..)
| TyKind::InferDelegation(..)
| TyKind::Err(_) => Self::Reborrow,
};
}

View File

@ -386,7 +386,8 @@ fn check_unsafe_derive_deserialize<'tcx>(
&& cx
.tcx
.inherent_impls(def.did())
.iter()
.into_iter()
.flatten()
.map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local()))
.any(|imp| has_unsafe(cx, imp))
{
@ -451,12 +452,12 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r
&& cx.tcx.is_diagnostic_item(sym::PartialEq, def_id)
&& !has_non_exhaustive_attr(cx.tcx, *adt)
&& let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id)
&& !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(),&[])
&& !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[])
// If all of our fields implement `Eq`, we can implement `Eq` too
&& adt
.all_fields()
.map(|f| f.ty(cx.tcx, args))
.all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(), &[]))
.all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[]))
{
span_lint_and_sugg(
cx,

View File

@ -6,7 +6,7 @@ use clippy_utils::diagnostics::span_lint;
use rustc_ast::{CoroutineKind, Fn, FnRetTy, Item, ItemKind};
use rustc_data_structures::sync::Lrc;
use rustc_errors::emitter::HumanEmitter;
use rustc_errors::DiagCtxt;
use rustc_errors::{DiagCtxt, DiagnosticBuilder};
use rustc_lint::LateContext;
use rustc_parse::maybe_new_parser_from_source_str;
use rustc_parse::parser::ForceCollect;
@ -53,7 +53,7 @@ pub fn check(
let mut parser = match maybe_new_parser_from_source_str(&sess, filename, code) {
Ok(p) => p,
Err(errs) => {
drop(errs);
errs.into_iter().for_each(DiagnosticBuilder::cancel);
return (false, test_attr_spans);
},
};

View File

@ -51,7 +51,8 @@ fn unary_pattern(pat: &Pat<'_>) -> bool {
| PatKind::Binding(..)
| PatKind::Wild
| PatKind::Never
| PatKind::Or(_) => false,
| PatKind::Or(_)
| PatKind::Err(_) => false,
PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)),
PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => etc.as_opt_usize().is_none() && array_rec(a),
PatKind::Ref(x, _) | PatKind::Box(x) => unary_pattern(x),

View File

@ -210,7 +210,7 @@ enum ImplicitHasherType<'tcx> {
impl<'tcx> ImplicitHasherType<'tcx> {
/// Checks that `ty` is a target type without a `BuildHasher`.
fn new(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> Option<Self> {
fn new(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Option<Self> {
if let TyKind::Path(QPath::Resolved(None, path)) = hir_ty.kind {
let params: Vec<_> = path
.segments

View File

@ -3,6 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::get_parent_expr;
use clippy_utils::source::snippet_with_context;
use rustc_ast::ast::{LitIntType, LitKind};
use rustc_data_structures::packed::Pu128;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
@ -69,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingAdd {
&& clippy_utils::SpanlessEq::new(cx).eq_expr(l, target)
&& BinOpKind::Add == op1.node
&& let ExprKind::Lit(lit) = value.kind
&& let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node
&& let LitKind::Int(Pu128(1), LitIntType::Unsuffixed) = lit.node
&& block.expr.is_none()
{
let mut app = Applicability::MachineApplicable;

View File

@ -1,6 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::{higher, is_integer_literal, peel_blocks_with_stmt, SpanlessEq};
use rustc_ast::ast::LitKind;
use rustc_data_structures::packed::Pu128;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass};
@ -86,7 +87,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
match cond_num_val.kind {
ExprKind::Lit(cond_lit) => {
// Check if the constant is zero
if let LitKind::Int(0, _) = cond_lit.node {
if let LitKind::Int(Pu128(0), _) = cond_lit.node {
if cx.typeck_results().expr_ty(cond_left).is_signed() {
} else {
print_lint_and_sugg(cx, var_name, expr);

View File

@ -53,9 +53,12 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl {
// List of spans to lint. (lint_span, first_span)
let mut lint_spans = Vec::new();
let Ok(impls) = cx.tcx.crate_inherent_impls(()) else {
return;
};
let inherent_impls = cx
.tcx
.with_stable_hashing_context(|hcx| cx.tcx.crate_inherent_impls(()).inherent_impls.to_sorted(&hcx, true));
.with_stable_hashing_context(|hcx| impls.inherent_impls.to_sorted(&hcx, true));
for (_, impl_ids) in inherent_impls.into_iter().filter(|(&id, impls)| {
impls.len() > 1

View File

@ -139,7 +139,7 @@ fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl Iter
fn adt_has_inherent_method(cx: &LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> bool {
if let Some(ty_did) = ty.ty_adt_def().map(ty::AdtDef::did) {
cx.tcx.inherent_impls(ty_did).iter().any(|&did| {
cx.tcx.inherent_impls(ty_did).into_iter().flatten().any(|&did| {
cx.tcx
.associated_items(did)
.filter_by_name_unhygienic(method_name)

View File

@ -441,7 +441,8 @@ fn check_for_is_empty(
let is_empty = cx
.tcx
.inherent_impls(impl_ty)
.iter()
.into_iter()
.flatten()
.flat_map(|&id| cx.tcx.associated_items(id).filter_by_name_unhygienic(is_empty))
.find(|item| item.kind == AssocKind::Fn);
@ -605,7 +606,7 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
/// Checks the inherent impl's items for an `is_empty(self)` method.
fn has_is_empty_impl(cx: &LateContext<'_>, id: DefId) -> bool {
let is_empty = sym!(is_empty);
cx.tcx.inherent_impls(id).iter().any(|imp| {
cx.tcx.inherent_impls(id).into_iter().flatten().any(|imp| {
cx.tcx
.associated_items(*imp)
.filter_by_name_unhygienic(is_empty)

View File

@ -118,7 +118,7 @@ fn is_ref_iterable<'tcx>(
.liberate_late_bound_regions(fn_id, cx.tcx.fn_sig(fn_id).skip_binder())
&& let &[req_self_ty, req_res_ty] = &**sig.inputs_and_output
&& let param_env = cx.tcx.param_env(fn_id)
&& implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, fn_id, &[])
&& implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, Some(fn_id), &[])
&& let Some(into_iter_ty) =
make_normalized_projection_with_regions(cx.tcx, param_env, trait_id, sym!(IntoIter), [req_self_ty])
&& let req_res_ty = normalize_with_regions(cx.tcx, param_env, req_res_ty)

View File

@ -461,7 +461,7 @@ fn is_array_length_equal_to_range(cx: &LateContext<'_>, start: &Expr<'_>, end: &
if let ExprKind::Lit(lit) = expr.kind
&& let ast::LitKind::Int(value, _) = lit.node
{
Some(value)
Some(value.get())
} else {
None
}

View File

@ -209,8 +209,8 @@ fn is_end_eq_array_len<'tcx>(
&& let Some(arr_len) = arr_len_const.try_eval_target_usize(cx.tcx, cx.param_env)
{
return match limits {
ast::RangeLimits::Closed => end_int + 1 >= arr_len.into(),
ast::RangeLimits::HalfOpen => end_int >= arr_len.into(),
ast::RangeLimits::Closed => end_int.get() + 1 >= arr_len.into(),
ast::RangeLimits::HalfOpen => end_int.get() >= arr_len.into(),
};
}

View File

@ -3,6 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::get_parent_expr;
use clippy_utils::source::snippet_with_context;
use rustc_ast::ast::LitKind;
use rustc_data_structures::packed::Pu128;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, GenericArg, QPath};
use rustc_lint::{LateContext, LateLintPass, LintContext};
@ -62,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualBits {
&& let Some((real_ty, resolved_ty, other_expr)) = get_one_size_of_ty(cx, left_expr, right_expr)
&& matches!(resolved_ty.kind(), ty::Int(_) | ty::Uint(_))
&& let ExprKind::Lit(lit) = &other_expr.kind
&& let LitKind::Int(8, _) = lit.node
&& let LitKind::Int(Pu128(8), _) = lit.node
{
let mut app = Applicability::MachineApplicable;
let ty_snip = snippet_with_context(cx, real_ty.span, ctxt, "..", &mut app).0;

View File

@ -45,7 +45,7 @@ fn expr_as_i128(expr: &Expr<'_>) -> Option<i128> {
&& let LitKind::Int(num, _) = lit.node
{
// Intentionally not handling numbers greater than i128::MAX (for u128 literals) for now.
num.try_into().ok()
num.get().try_into().ok()
} else {
None
}

View File

@ -161,7 +161,7 @@ fn eq_pattern_length<'tcx>(cx: &LateContext<'tcx>, pattern: &Expr<'_>, expr: &'t
..
}) = expr.kind
{
constant_length(cx, pattern).map_or(false, |length| length == *n)
constant_length(cx, pattern).map_or(false, |length| *n == length)
} else {
len_arg(cx, expr).map_or(false, |arg| eq_expr_value(cx, pattern, arg))
}

View File

@ -11,7 +11,7 @@ use rustc_hir::{Arm, Expr, ExprKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, P
use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_span::Symbol;
use rustc_span::{ErrorGuaranteed, Symbol};
use super::MATCH_SAME_ARMS;
@ -167,6 +167,8 @@ enum NormalizedPat<'a> {
/// contains everything afterwards. Note that either side, or both sides, may contain zero
/// patterns.
Slice(&'a [Self], Option<&'a [Self]>),
/// A placeholder for a pattern that wasn't well formed in some way.
Err(ErrorGuaranteed),
}
#[derive(Clone, Copy)]
@ -291,7 +293,7 @@ impl<'a> NormalizedPat<'a> {
LitKind::ByteStr(ref bytes, _) | LitKind::CStr(ref bytes, _) => Self::LitBytes(bytes),
LitKind::Byte(val) => Self::LitInt(val.into()),
LitKind::Char(val) => Self::LitInt(val.into()),
LitKind::Int(val, _) => Self::LitInt(val),
LitKind::Int(val, _) => Self::LitInt(val.get()),
LitKind::Bool(val) => Self::LitBool(val),
LitKind::Float(..) | LitKind::Err => Self::Wild,
},
@ -303,7 +305,7 @@ impl<'a> NormalizedPat<'a> {
None => 0,
Some(e) => match &e.kind {
ExprKind::Lit(lit) => match lit.node {
LitKind::Int(val, _) => val,
LitKind::Int(val, _) => val.get(),
LitKind::Char(val) => val.into(),
LitKind::Byte(val) => val.into(),
_ => return Self::Wild,
@ -315,7 +317,7 @@ impl<'a> NormalizedPat<'a> {
None => (u128::MAX, RangeEnd::Included),
Some(e) => match &e.kind {
ExprKind::Lit(lit) => match lit.node {
LitKind::Int(val, _) => (val, bounds),
LitKind::Int(val, _) => (val.get(), bounds),
LitKind::Char(val) => (val.into(), bounds),
LitKind::Byte(val) => (val.into(), bounds),
_ => return Self::Wild,
@ -329,6 +331,7 @@ impl<'a> NormalizedPat<'a> {
arena.alloc_from_iter(front.iter().map(|pat| Self::from_pat(cx, arena, pat))),
wild_pat.map(|_| &*arena.alloc_from_iter(back.iter().map(|pat| Self::from_pat(cx, arena, pat)))),
),
PatKind::Err(guar) => Self::Err(guar),
}
}

View File

@ -2,6 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
use rustc_ast::LitKind;
use rustc_data_structures::packed::Pu128;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
@ -20,7 +21,7 @@ pub(super) fn check<'tcx>(
&& let Some(impl_id) = cx.tcx.impl_of_method(method_id)
&& let identity = cx.tcx.type_of(impl_id).instantiate_identity()
&& let hir::ExprKind::Lit(Spanned {
node: LitKind::Int(0, _),
node: LitKind::Int(Pu128(0), _),
..
}) = arg.kind
{

View File

@ -13,7 +13,7 @@ fn expr_as_u128(cx: &LateContext<'_>, e: &Expr<'_>) -> Option<u128> {
if let ExprKind::Lit(lit) = expr_or_init(cx, e).kind
&& let LitKind::Int(n, _) = lit.node
{
Some(n)
Some(n.get())
} else {
None
}

View File

@ -73,7 +73,8 @@ pub(super) fn check<'tcx>(
let has_suggested_method = receiver_ty.ty_adt_def().is_some_and(|adt_def| {
cx.tcx
.inherent_impls(adt_def.did())
.iter()
.into_iter()
.flatten()
.flat_map(|impl_id| cx.tcx.associated_items(impl_id).filter_by_name_unhygienic(sugg))
.any(|assoc| {
assoc.fn_has_self_parameter

View File

@ -1,4 +1,5 @@
use rustc_ast::ast::{LitIntType, LitKind};
use rustc_data_structures::packed::Pu128;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
@ -41,7 +42,7 @@ fn arg_is_seek_from_current<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>)
// check if argument of `SeekFrom::Current` is `0`
if args.len() == 1
&& let ExprKind::Lit(lit) = args[0].kind
&& let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node
&& let LitKind::Int(Pu128(0), LitIntType::Unsuffixed) = lit.node
{
return true;
}

View File

@ -2,6 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::implements_trait;
use clippy_utils::{is_expr_used_or_unified, match_def_path, paths};
use rustc_ast::ast::{LitIntType, LitKind};
use rustc_data_structures::packed::Pu128;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
@ -31,7 +32,7 @@ pub(super) fn check<'tcx>(
&& match_def_path(cx, def_id, &paths::STD_IO_SEEKFROM_START)
&& args1.len() == 1
&& let ExprKind::Lit(lit) = args1[0].kind
&& let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node
&& let LitKind::Int(Pu128(0), LitIntType::Unsuffixed) = lit.node
{
let method_call_span = expr.span.with_lo(name_span.lo());
span_lint_and_then(

View File

@ -2,6 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{is_trait_method, path_to_local_id, peel_blocks, strip_pat_refs};
use rustc_ast::ast;
use rustc_data_structures::packed::Pu128;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::PatKind;
@ -150,7 +151,7 @@ pub(super) fn check(
},
);
},
ast::LitKind::Int(0, _) => check_fold_with_op(
ast::LitKind::Int(Pu128(0), _) => check_fold_with_op(
cx,
expr,
acc,
@ -162,7 +163,7 @@ pub(super) fn check(
method_name: "sum",
},
),
ast::LitKind::Int(1, _) => {
ast::LitKind::Int(Pu128(1), _) => {
check_fold_with_op(
cx,
expr,

View File

@ -1,6 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::is_type_diagnostic_item;
use rustc_ast::LitKind;
use rustc_data_structures::packed::Pu128;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
@ -20,7 +21,7 @@ pub(super) fn check<'tcx>(
&& let Some(impl_id) = cx.tcx.impl_of_method(method_id)
&& is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::Vec)
&& let ExprKind::Lit(Spanned {
node: LitKind::Int(0, _),
node: LitKind::Int(Pu128(0), _),
..
}) = count_arg.kind
&& let ExprKind::Lit(Spanned {

View File

@ -7,6 +7,7 @@ use clippy_utils::source::snippet;
use clippy_utils::visitors::for_each_expr;
use clippy_utils::{eq_expr_value, hash_expr, higher};
use rustc_ast::{LitKind, RangeLimits};
use rustc_data_structures::packed::Pu128;
use rustc_data_structures::unhash::UnhashMap;
use rustc_errors::{Applicability, Diagnostic};
use rustc_hir::{BinOp, Block, Body, Expr, ExprKind, UnOp};
@ -102,8 +103,8 @@ fn len_comparison<'hir>(
) -> Option<(LengthComparison, usize, &'hir Expr<'hir>)> {
macro_rules! int_lit_pat {
($id:ident) => {
ExprKind::Lit(Spanned {
node: LitKind::Int($id, _),
ExprKind::Lit(&Spanned {
node: LitKind::Int(Pu128($id), _),
..
})
};
@ -112,13 +113,13 @@ fn len_comparison<'hir>(
// normalize comparison, `v.len() > 4` becomes `4 < v.len()`
// this simplifies the logic a bit
let (op, left, right) = normalize_comparison(bin_op.node, left, right)?;
match (op, &left.kind, &right.kind) {
(Rel::Lt, int_lit_pat!(left), _) => Some((LengthComparison::IntLessThanLength, *left as usize, right)),
(Rel::Lt, _, int_lit_pat!(right)) => Some((LengthComparison::LengthLessThanInt, *right as usize, left)),
(Rel::Le, int_lit_pat!(left), _) => Some((LengthComparison::IntLessThanOrEqualLength, *left as usize, right)),
(Rel::Le, _, int_lit_pat!(right)) => Some((LengthComparison::LengthLessThanOrEqualInt, *right as usize, left)),
(Rel::Eq, int_lit_pat!(left), _) => Some((LengthComparison::LengthEqualInt, *left as usize, right)),
(Rel::Eq, _, int_lit_pat!(right)) => Some((LengthComparison::LengthEqualInt, *right as usize, left)),
match (op, left.kind, right.kind) {
(Rel::Lt, int_lit_pat!(left), _) => Some((LengthComparison::IntLessThanLength, left as usize, right)),
(Rel::Lt, _, int_lit_pat!(right)) => Some((LengthComparison::LengthLessThanInt, right as usize, left)),
(Rel::Le, int_lit_pat!(left), _) => Some((LengthComparison::IntLessThanOrEqualLength, left as usize, right)),
(Rel::Le, _, int_lit_pat!(right)) => Some((LengthComparison::LengthLessThanOrEqualInt, right as usize, left)),
(Rel::Eq, int_lit_pat!(left), _) => Some((LengthComparison::LengthEqualInt, left as usize, right)),
(Rel::Eq, _, int_lit_pat!(right)) => Some((LengthComparison::LengthEqualInt, right as usize, left)),
_ => None,
}
}
@ -206,14 +207,14 @@ impl<'hir> IndexEntry<'hir> {
/// for `..=5` this returns `Some(5)`
fn upper_index_expr(expr: &Expr<'_>) -> Option<usize> {
if let ExprKind::Lit(lit) = &expr.kind
&& let LitKind::Int(index, _) = lit.node
&& let LitKind::Int(Pu128(index), _) = lit.node
{
Some(index as usize)
} else if let Some(higher::Range {
end: Some(end), limits, ..
}) = higher::Range::hir(expr)
&& let ExprKind::Lit(lit) = &end.kind
&& let LitKind::Int(index @ 1.., _) = lit.node
&& let LitKind::Int(Pu128(index @ 1..), _) = lit.node
{
match limits {
RangeLimits::HalfOpen => Some(index as usize - 1),

View File

@ -151,7 +151,7 @@ impl ArithmeticSideEffects {
if let hir::ExprKind::Lit(lit) = actual.kind
&& let ast::LitKind::Int(n, _) = lit.node
{
return Some(n);
return Some(n.get());
}
if let Some(Constant::Int(n)) = constant(cx, cx.typeck_results(), expr) {
return Some(n);

View File

@ -1,6 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::sugg::Sugg;
use rustc_ast::ast::LitKind;
use rustc_data_structures::packed::Pu128;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::LateContext;
@ -19,9 +20,9 @@ pub(super) fn check<'tcx>(
&& let ExprKind::Binary(op1, left1, right1) = &left.kind
&& BinOpKind::BitAnd == op1.node
&& let ExprKind::Lit(lit) = &right1.kind
&& let LitKind::Int(n, _) = lit.node
&& let LitKind::Int(Pu128(n), _) = lit.node
&& let ExprKind::Lit(lit1) = &right.kind
&& let LitKind::Int(0, _) = lit1.node
&& let LitKind::Int(Pu128(0), _) = lit1.node
&& n.leading_zeros() == n.count_zeros()
&& n > u128::from(threshold)
{

View File

@ -257,9 +257,9 @@ fn is_call_with_ref_arg<'tcx>(
..
} = kind
&& args.len() == 1
&& let mir::Operand::Move(mir::Place { local, .. }) = &args[0]
&& let mir::Operand::Move(mir::Place { local, .. }) = &args[0].node
&& let ty::FnDef(def_id, _) = *func.ty(mir, cx.tcx).kind()
&& let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(mir, cx.tcx))
&& let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].node.ty(mir, cx.tcx))
&& !is_copy(cx, inner_ty)
{
Some((def_id, *local, inner_ty, destination.as_local()?))

View File

@ -5,7 +5,9 @@ use clippy_utils::sugg::Sugg;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor};
use rustc_hir::{intravisit as hir_visit, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Node};
use rustc_hir::{
intravisit as hir_visit, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, ExprKind, Node,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter;
use rustc_middle::lint::in_external_macro;
@ -166,10 +168,22 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
if coroutine_kind.is_async()
&& let hir::ExprKind::Closure(closure) = body.kind
{
let async_closure_body = cx.tcx.hir().body(closure.body);
// Like `async fn`, async closures are wrapped in an additional block
// to move all of the closure's arguments into the future.
let async_closure_body = cx.tcx.hir().body(closure.body).value;
let ExprKind::Block(block, _) = async_closure_body.kind else {
return;
};
let Some(block_expr) = block.expr else {
return;
};
let ExprKind::DropTemps(body_expr) = block_expr.kind else {
return;
};
// `async x` is a syntax error, so it becomes `async { x }`
if !matches!(async_closure_body.value.kind, hir::ExprKind::Block(_, _)) {
if !matches!(body_expr.kind, hir::ExprKind::Block(_, _)) {
hint = hint.blockify();
}

View File

@ -314,9 +314,9 @@ impl_lint_pass!(Types => [BOX_COLLECTION, VEC_BOX, OPTION_OPTION, LINKEDLIST, BO
impl<'tcx> LateLintPass<'tcx> for Types {
fn check_fn(
&mut self,
cx: &LateContext<'_>,
cx: &LateContext<'tcx>,
fn_kind: FnKind<'_>,
decl: &FnDecl<'_>,
decl: &FnDecl<'tcx>,
_: &Body<'_>,
_: Span,
def_id: LocalDefId,
@ -346,7 +346,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
);
}
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id);
match item.kind {
@ -363,7 +363,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
}
}
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'tcx>) {
match item.kind {
ImplItemKind::Const(ty, _) => {
let is_in_trait_impl = if let Some(hir::Node::Item(item)) = cx
@ -391,7 +391,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
}
}
fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
fn check_field_def(&mut self, cx: &LateContext<'tcx>, field: &hir::FieldDef<'tcx>) {
let is_exported = cx.effective_visibilities.is_exported(field.def_id);
self.check_ty(
@ -404,7 +404,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
);
}
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'_>) {
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'tcx>) {
let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id);
let context = CheckTyContext {
@ -421,7 +421,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
}
}
fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &Local<'tcx>) {
if let Some(ty) = local.ty {
self.check_ty(
cx,
@ -444,7 +444,7 @@ impl Types {
}
}
fn check_fn_decl(&mut self, cx: &LateContext<'_>, decl: &FnDecl<'_>, context: CheckTyContext) {
fn check_fn_decl<'tcx>(&mut self, cx: &LateContext<'tcx>, decl: &FnDecl<'tcx>, context: CheckTyContext) {
// Ignore functions in trait implementations as they are usually forced by the trait definition.
//
// FIXME: ideally we would like to warn *if the complicated type can be simplified*, but it's hard
@ -466,7 +466,7 @@ impl Types {
/// lint found.
///
/// The parameter `is_local` distinguishes the context of the type.
fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, mut context: CheckTyContext) {
fn check_ty<'tcx>(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, mut context: CheckTyContext) {
if hir_ty.span.from_expansion() {
return;
}

View File

@ -11,7 +11,7 @@ use rustc_span::symbol::sym;
use super::{utils, REDUNDANT_ALLOCATION};
pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath: &QPath<'tcx>, def_id: DefId) -> bool {
let mut applicability = Applicability::MaybeIncorrect;
let outer_sym = if Some(def_id) == cx.tcx.lang_items().owned_box() {
"Box"

View File

@ -13,10 +13,10 @@ use rustc_span::symbol::sym;
use super::VEC_BOX;
pub(super) fn check(
cx: &LateContext<'_>,
pub(super) fn check<'tcx>(
cx: &LateContext<'tcx>,
hir_ty: &hir::Ty<'_>,
qpath: &QPath<'_>,
qpath: &QPath<'tcx>,
def_id: DefId,
box_size_threshold: u64,
) -> bool {

View File

@ -77,7 +77,7 @@ fn get_ty_def_id(ty: Ty<'_>) -> Option<DefId> {
}
}
fn get_hir_ty_def_id(tcx: TyCtxt<'_>, hir_ty: rustc_hir::Ty<'_>) -> Option<DefId> {
fn get_hir_ty_def_id<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: rustc_hir::Ty<'tcx>) -> Option<DefId> {
let TyKind::Path(qpath) = hir_ty.kind else { return None };
match qpath {
QPath::Resolved(_, path) => path.res.opt_def_id(),
@ -237,7 +237,7 @@ fn check_to_string(cx: &LateContext<'_>, method_span: Span, method_def_id: Local
}
}
fn is_default_method_on_current_ty(tcx: TyCtxt<'_>, qpath: QPath<'_>, implemented_ty_id: DefId) -> bool {
fn is_default_method_on_current_ty<'tcx>(tcx: TyCtxt<'tcx>, qpath: QPath<'tcx>, implemented_ty_id: DefId) -> bool {
match qpath {
QPath::Resolved(_, path) => match path.segments {
[first, .., last] => last.ident.name == kw::Default && first.res.opt_def_id() == Some(implemented_ty_id),

View File

@ -57,11 +57,11 @@ impl LateLintPass<'_> for UninhabitedReferences {
}
}
fn check_fn(
fn check_fn<'tcx>(
&mut self,
cx: &LateContext<'_>,
cx: &LateContext<'tcx>,
kind: FnKind<'_>,
fndecl: &'_ FnDecl<'_>,
fndecl: &'_ FnDecl<'tcx>,
_: &'_ Body<'_>,
span: Span,
_: LocalDefId,

View File

@ -226,7 +226,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec<P<Pat>>, focus_idx: us
// Therefore they are not some form of constructor `C`,
// with which a pattern `C(p_0)` may be formed,
// which we would want to join with other `C(p_j)`s.
Ident(.., None) | Lit(_) | Wild | Never | Path(..) | Range(..) | Rest | MacCall(_)
Ident(.., None) | Lit(_) | Wild | Err(_) | Never | Path(..) | Range(..) | Rest | MacCall(_)
// Skip immutable refs, as grouping them saves few characters,
// and almost always requires adding parens (increasing noisiness).
// In the case of only two patterns, replacement adds net characters.

View File

@ -207,7 +207,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
}
}
fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) {
fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) {
if !hir_ty.span.from_expansion()
&& self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS)
&& let Some(&StackItem::Check {

View File

@ -710,6 +710,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
self.slice(start, |pat| self.pat(pat));
self.slice(end, |pat| self.pat(pat));
},
PatKind::Err(_) => kind!("Err"),
}
}

View File

@ -41,7 +41,6 @@ impl CompilerLintFunctions {
pub fn new() -> Self {
let mut map = FxHashMap::default();
map.insert("span_lint", "utils::span_lint");
map.insert("struct_span_lint", "utils::span_lint");
map.insert("lint", "utils::span_lint");
map.insert("span_lint_note", "utils::span_lint_and_note");
map.insert("span_lint_help", "utils::span_lint_and_help");

View File

@ -71,7 +71,9 @@ pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool {
SimplifiedType::Str,
]
.iter()
.flat_map(|&ty| cx.tcx.incoherent_impls(ty).iter().copied());
.flat_map(|&ty| cx.tcx.incoherent_impls(ty).into_iter())
.flatten()
.copied();
for item_def_id in lang_items.iter().map(|(_, def_id)| def_id).chain(incoherent_impls) {
let lang_item_path = cx.get_def_path(item_def_id);
if path_syms.starts_with(&lang_item_path) {

View File

@ -44,7 +44,7 @@ declare_clippy_lint! {
declare_lint_pass!(ZeroSizedMapValues => [ZERO_SIZED_MAP_VALUES]);
impl LateLintPass<'_> for ZeroSizedMapValues {
fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) {
fn check_ty<'tcx>(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) {
if !hir_ty.span.from_expansion()
&& !in_trait_impl(cx, hir_ty.hir_id)
&& let ty = ty_from_hir_ty(cx, hir_ty)
@ -82,7 +82,7 @@ fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool {
false
}
fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
cx.maybe_typeck_results()
.and_then(|results| {
if results.hir_owner == hir_ty.hir_id.owner {

View File

@ -275,7 +275,7 @@ pub fn lit_to_mir_constant<'tcx>(lit: &LitKind, ty: Option<Ty<'tcx>>) -> Constan
LitKind::Byte(b) => Constant::Int(u128::from(b)),
LitKind::ByteStr(ref s, _) | LitKind::CStr(ref s, _) => Constant::Binary(Lrc::clone(s)),
LitKind::Char(c) => Constant::Char(c),
LitKind::Int(n, _) => Constant::Int(n),
LitKind::Int(n, _) => Constant::Int(n.get()),
LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty {
ast::FloatTy::F32 => Constant::F32(is.as_str().parse().unwrap()),
ast::FloatTy::F64 => Constant::F64(is.as_str().parse().unwrap()),

View File

@ -47,7 +47,7 @@ fn docs_link(diag: &mut Diagnostic, lint: &'static Lint) {
/// ```
pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<MultiSpan>, msg: &str) {
#[expect(clippy::disallowed_methods)]
cx.struct_span_lint(lint, sp, msg.to_string(), |diag| {
cx.span_lint(lint, sp, msg.to_string(), |diag| {
docs_link(diag, lint);
});
}
@ -81,7 +81,7 @@ pub fn span_lint_and_help<T: LintContext>(
help: &str,
) {
#[expect(clippy::disallowed_methods)]
cx.struct_span_lint(lint, span, msg.to_string(), |diag| {
cx.span_lint(lint, span, msg.to_string(), |diag| {
let help = help.to_string();
if let Some(help_span) = help_span {
diag.span_help(help_span, help);
@ -124,7 +124,7 @@ pub fn span_lint_and_note<T: LintContext>(
note: &str,
) {
#[expect(clippy::disallowed_methods)]
cx.struct_span_lint(lint, span, msg.to_string(), |diag| {
cx.span_lint(lint, span, msg.to_string(), |diag| {
let note = note.to_string();
if let Some(note_span) = note_span {
diag.span_note(note_span, note);
@ -146,7 +146,7 @@ where
F: FnOnce(&mut Diagnostic),
{
#[expect(clippy::disallowed_methods)]
cx.struct_span_lint(lint, sp, msg.to_string(), |diag| {
cx.span_lint(lint, sp, msg.to_string(), |diag| {
f(diag);
docs_link(diag, lint);
});
@ -154,7 +154,7 @@ where
pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) {
#[expect(clippy::disallowed_methods)]
cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg.to_string(), |diag| {
cx.tcx.node_span_lint(lint, hir_id, sp, msg.to_string(), |diag| {
docs_link(diag, lint);
});
}
@ -168,7 +168,7 @@ pub fn span_lint_hir_and_then(
f: impl FnOnce(&mut Diagnostic),
) {
#[expect(clippy::disallowed_methods)]
cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg.to_string(), |diag| {
cx.tcx.node_span_lint(lint, hir_id, sp, msg.to_string(), |diag| {
f(diag);
docs_link(diag, lint);
});

View File

@ -1007,7 +1007,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
}
e.hash(&mut self.s);
},
PatKind::Never | PatKind::Wild => {},
PatKind::Never | PatKind::Wild | PatKind::Err(_) => {},
}
}
@ -1108,7 +1108,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
TyKind::Typeof(anon_const) => {
self.hash_body(anon_const.body);
},
TyKind::Err(_) | TyKind::Infer | TyKind::Never => {},
TyKind::Err(_) | TyKind::Infer | TyKind::Never | TyKind::InferDelegation(..) => {},
}
}

View File

@ -80,6 +80,7 @@ use std::sync::{Mutex, MutexGuard, OnceLock};
use itertools::Itertools;
use rustc_ast::ast::{self, LitKind, RangeLimits};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::packed::Pu128;
use rustc_data_structures::unhash::UnhashMap;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, LOCAL_CRATE};
@ -534,10 +535,16 @@ fn find_primitive_impls<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator<It
"u128" => SimplifiedType::Uint(UintTy::U128),
"f32" => SimplifiedType::Float(FloatTy::F32),
"f64" => SimplifiedType::Float(FloatTy::F64),
_ => return [].iter().copied(),
#[allow(trivial_casts)]
_ => {
return Result::<_, rustc_errors::ErrorGuaranteed>::Ok(&[] as &[_])
.into_iter()
.flatten()
.copied();
},
};
tcx.incoherent_impls(ty).iter().copied()
tcx.incoherent_impls(ty).into_iter().flatten().copied()
}
fn non_local_item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Res> {
@ -663,7 +670,8 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Vec<Res> {
// `impl S { ... }`
let inherent_impl_children = tcx
.inherent_impls(def_id)
.iter()
.into_iter()
.flatten()
.flat_map(|&impl_def_id| item_children_by_name(tcx, impl_def_id, segment));
let direct_children = item_children_by_name(tcx, def_id, segment);
@ -836,7 +844,7 @@ pub fn is_default_equivalent_call(cx: &LateContext<'_>, repl_func: &Expr<'_>) ->
pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
match &e.kind {
ExprKind::Lit(lit) => match lit.node {
LitKind::Bool(false) | LitKind::Int(0, _) => true,
LitKind::Bool(false) | LitKind::Int(Pu128(0), _) => true,
LitKind::Str(s, _) => s.is_empty(),
_ => false,
},
@ -1709,7 +1717,6 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
PatKind::Wild | PatKind::Never => false, // If `!` typechecked then the type is empty, so not refutable.
PatKind::Binding(_, _, _, pat) => pat.map_or(false, |pat| is_refutable(cx, pat)),
PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat),
PatKind::Lit(..) | PatKind::Range(..) => true,
PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id),
PatKind::Or(pats) => {
// TODO: should be the honest check, that pats is exhaustive set
@ -1733,6 +1740,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
},
}
},
PatKind::Lit(..) | PatKind::Range(..) | PatKind::Err(_) => true,
}
}

View File

@ -104,7 +104,7 @@ impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b,
let mut mutable_borrowers = vec![];
for op in args {
match op {
match &op.node {
mir::Operand::Copy(p) | mir::Operand::Move(p) => {
if let ty::Ref(_, _, Mutability::Mut) = self.body.local_decls[p.local].ty.kind() {
mutable_borrowers.push(p.local);

View File

@ -345,7 +345,7 @@ fn check_terminator<'tcx>(
check_operand(tcx, func, span, body)?;
for arg in args {
check_operand(tcx, arg, span, body)?;
check_operand(tcx, &arg.node, span, body)?;
}
Ok(())
} else {

View File

@ -214,36 +214,22 @@ pub fn implements_trait<'tcx>(
trait_id: DefId,
args: &[GenericArg<'tcx>],
) -> bool {
let callee_id = cx
.enclosing_body
.map(|body| cx.tcx.hir().body_owner(body).owner.to_def_id());
implements_trait_with_env_from_iter(
cx.tcx,
cx.param_env,
ty,
trait_id,
callee_id,
args.iter().map(|&x| Some(x)),
)
implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, trait_id, None, args.iter().map(|&x| Some(x)))
}
/// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context.
///
/// The `callee_id` argument is used to determine whether this is a function call in a `const fn`
/// environment, used for checking const traits.
pub fn implements_trait_with_env<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
ty: Ty<'tcx>,
trait_id: DefId,
callee_id: DefId,
callee_id: Option<DefId>,
args: &[GenericArg<'tcx>],
) -> bool {
implements_trait_with_env_from_iter(
tcx,
param_env,
ty,
trait_id,
Some(callee_id),
args.iter().map(|&x| Some(x)),
)
implements_trait_with_env_from_iter(tcx, param_env, ty, trait_id, callee_id, args.iter().map(|&x| Some(x)))
}
/// Same as `implements_trait_from_env` but takes the arguments as an iterator.
@ -258,6 +244,13 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
// Clippy shouldn't have infer types
assert!(!ty.has_infer());
// If a `callee_id` is passed, then we assert that it is a body owner
// through calling `body_owner_kind`, which would panic if the callee
// does not have a body.
if let Some(callee_id) = callee_id {
let _ = tcx.hir().body_owner_kind(callee_id);
}
let ty = tcx.erase_regions(ty);
if ty.has_escaping_bound_vars() {
return false;

View File

@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2024-01-11"
channel = "nightly-2024-01-25"
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]

View File

@ -11,7 +11,7 @@ use rustc_lint::{Lint, LintContext};
use rustc_middle::ty::TyCtxt;
pub fn a(cx: impl LintContext, lint: &'static Lint, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) {
cx.struct_span_lint(lint, span, msg, |_| {});
cx.span_lint(lint, span, msg, |_| {});
}
pub fn b(
@ -21,7 +21,7 @@ pub fn b(
span: impl Into<MultiSpan>,
msg: impl Into<DiagnosticMessage>,
) {
tcx.struct_span_lint_hir(lint, hir_id, span, msg, |_| {});
tcx.node_span_lint(lint, hir_id, span, msg, |_| {});
}
fn main() {}

View File

@ -0,0 +1,17 @@
error: use of a disallowed method `rustc_lint::context::LintContext::span_lint`
--> $DIR/disallow_span_lint.rs:14:5
|
LL | cx.span_lint(lint, span, msg, |_| {});
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::disallowed-methods` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::disallowed_methods)]`
error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::node_span_lint`
--> $DIR/disallow_span_lint.rs:24:5
|
LL | tcx.node_span_lint(lint, hir_id, span, msg, |_| {});
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors

View File

@ -1,17 +0,0 @@
error: use of a disallowed method `rustc_lint::context::LintContext::struct_span_lint`
--> $DIR/disallow_struct_span_lint.rs:14:5
|
LL | cx.struct_span_lint(lint, span, msg, |_| {});
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::disallowed-methods` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::disallowed_methods)]`
error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::struct_span_lint_hir`
--> $DIR/disallow_struct_span_lint.rs:24:5
|
LL | tcx.struct_span_lint_hir(lint, hir_id, span, msg, |_| {});
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors

View File

@ -1 +1 @@
pub-underscore-fields-behavior = "PubliclyExported"
pub-underscore-fields-behavior = "PubliclyExported"

View File

@ -48,7 +48,11 @@ if let ExprKind::Closure { capture_clause: CaptureBy::Value { .. }, fn_decl: fn_
&& expr2 = &cx.tcx.hir().body(body_id1).value
&& let ExprKind::Block(block, None) = expr2.kind
&& block.stmts.is_empty()
&& block.expr.is_none()
&& let Some(trailing_expr) = block.expr
&& let ExprKind::DropTemps(expr3) = trailing_expr.kind
&& let ExprKind::Block(block1, None) = expr3.kind
&& block1.stmts.is_empty()
&& block1.expr.is_none()
{
// report your lint here
}

View File

@ -26,6 +26,7 @@ fn main() {
let _ = p_rw;
}
#[allow(let_underscore_lock)]
fn uplifted() {
// shouldn't lint std locks as they were uplifted as rustc's `let_underscore_lock`

View File

@ -7,10 +7,12 @@
#[warn(clippy::if_not_else)]
#[warn(clippy::unnecessary_cast)]
#[warn(clippy::useless_transmute)]
// Shouldn't suggest rustc lint name(`dead_code`)
#[warn(clippy::eq_op)]
// Should suggest rustc lint name(`dead_code`)
#[warn(dead_code)]
// Shouldn't suggest removed/deprecated clippy lint name(`unused_collect`)
#[warn(clippy::unused_self)]
// Shouldn't suggest renamed clippy lint name(`const_static_lifetime`)
#[warn(clippy::redundant_static_lifetimes)]
// issue #118183, should report `missing_docs` from rustc lint
#[warn(missing_docs)]
fn main() {}

View File

@ -7,10 +7,12 @@
#[warn(clippy::if_not_els)]
#[warn(clippy::UNNecsaRy_cAst)]
#[warn(clippy::useles_transute)]
// Shouldn't suggest rustc lint name(`dead_code`)
// Should suggest rustc lint name(`dead_code`)
#[warn(clippy::dead_cod)]
// Shouldn't suggest removed/deprecated clippy lint name(`unused_collect`)
#[warn(clippy::unused_colle)]
// Shouldn't suggest renamed clippy lint name(`const_static_lifetime`)
#[warn(clippy::const_static_lifetim)]
// issue #118183, should report `missing_docs` from rustc lint
#[warn(clippy::missing_docs)]
fn main() {}

View File

@ -35,7 +35,12 @@ error: unknown lint: `clippy::dead_cod`
--> $DIR/unknown_clippy_lints.rs:11:8
|
LL | #[warn(clippy::dead_cod)]
| ^^^^^^^^^^^^^^^^ help: did you mean: `clippy::eq_op`
| ^^^^^^^^^^^^^^^^
|
help: a lint with a similar name exists in `rustc` lints
|
LL | #[warn(dead_code)]
| ~~~~~~~~~
error: unknown lint: `clippy::unused_colle`
--> $DIR/unknown_clippy_lints.rs:13:8
@ -49,5 +54,16 @@ error: unknown lint: `clippy::const_static_lifetim`
LL | #[warn(clippy::const_static_lifetim)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::redundant_static_lifetimes`
error: aborting due to 8 previous errors
error: unknown lint: `clippy::missing_docs`
--> $DIR/unknown_clippy_lints.rs:17:8
|
LL | #[warn(clippy::missing_docs)]
| ^^^^^^^^^^^^^^^^^^^^
|
help: a lint with a similar name exists in `rustc` lints
|
LL | #[warn(missing_docs)]
| ~~~~~~~~~~~~
error: aborting due to 9 previous errors