mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Auto merge of #12200 - flip1995:rustup, r=flip1995
Rustup r? `@ghost` changelog: none
This commit is contained in:
commit
66c29b973b
@ -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"
|
||||
]
|
||||
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -830,6 +830,7 @@ impl TyCoercionStability {
|
||||
| TyKind::Infer
|
||||
| TyKind::Typeof(..)
|
||||
| TyKind::TraitObject(..)
|
||||
| TyKind::InferDelegation(..)
|
||||
| TyKind::Err(_) => Self::Reborrow,
|
||||
};
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
},
|
||||
};
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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(),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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()?))
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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 {
|
||||
|
@ -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),
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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()),
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -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(..) => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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"]
|
||||
|
@ -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() {}
|
17
tests/ui-internal/disallow_span_lint.stderr
Normal file
17
tests/ui-internal/disallow_span_lint.stderr
Normal 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
|
||||
|
@ -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
|
||||
|
@ -1 +1 @@
|
||||
pub-underscore-fields-behavior = "PubliclyExported"
|
||||
pub-underscore-fields-behavior = "PubliclyExported"
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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`
|
||||
|
||||
|
@ -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() {}
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user