Rustup (#15531)
Letting rustbot assign a reviewer, so that someone can double check
9de86f40d7.
changelog: none
This commit is contained in:
commit
877967959a
58 changed files with 430 additions and 305 deletions
|
|
@ -71,3 +71,7 @@ harness = false
|
|||
# without increasing total build times.
|
||||
[profile.dev.package.quine-mc_cluskey]
|
||||
opt-level = 3
|
||||
|
||||
[lints.rust.unexpected_cfgs]
|
||||
level = "warn"
|
||||
check-cfg = ['cfg(bootstrap)']
|
||||
|
|
|
|||
|
|
@ -534,6 +534,7 @@ fn get_item_name(item: &Item<'_>) -> Option<String> {
|
|||
|
||||
if let Some(of_trait) = im.of_trait {
|
||||
let mut trait_segs: Vec<String> = of_trait
|
||||
.trait_ref
|
||||
.path
|
||||
.segments
|
||||
.iter()
|
||||
|
|
|
|||
|
|
@ -130,18 +130,22 @@ impl<'tcx> LateLintPass<'tcx> for BoolAssertComparison {
|
|||
|
||||
let mut suggestions = vec![(name_span, non_eq_mac.to_string()), (lit_span, String::new())];
|
||||
|
||||
if bool_value ^ eq_macro {
|
||||
let Some(sugg) = Sugg::hir_opt(cx, non_lit_expr) else {
|
||||
return;
|
||||
if let Some(sugg) = Sugg::hir_opt(cx, non_lit_expr) {
|
||||
let sugg = if bool_value ^ eq_macro {
|
||||
!sugg.maybe_paren()
|
||||
} else if ty::Bool == *non_lit_ty.kind() {
|
||||
sugg
|
||||
} else {
|
||||
!!sugg.maybe_paren()
|
||||
};
|
||||
suggestions.push((non_lit_expr.span, (!sugg).to_string()));
|
||||
}
|
||||
suggestions.push((non_lit_expr.span, sugg.to_string()));
|
||||
|
||||
diag.multipart_suggestion(
|
||||
format!("replace it with `{non_eq_mac}!(..)`"),
|
||||
suggestions,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
diag.multipart_suggestion(
|
||||
format!("replace it with `{non_eq_mac}!(..)`"),
|
||||
suggestions,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,12 +37,12 @@ declare_lint_pass!(CopyIterator => [COPY_ITERATOR]);
|
|||
impl<'tcx> LateLintPass<'tcx> for CopyIterator {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
if let ItemKind::Impl(Impl {
|
||||
of_trait: Some(trait_ref),
|
||||
of_trait: Some(of_trait),
|
||||
..
|
||||
}) = item.kind
|
||||
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
|
||||
&& is_copy(cx, ty)
|
||||
&& let Some(trait_id) = trait_ref.trait_def_id()
|
||||
&& let Some(trait_id) = of_trait.trait_ref.trait_def_id()
|
||||
&& cx.tcx.is_diagnostic_item(sym::Iterator, trait_id)
|
||||
{
|
||||
span_lint_and_note(
|
||||
|
|
|
|||
|
|
@ -183,14 +183,14 @@ fn check_enum<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>, func_expr: &Ex
|
|||
impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
if let ItemKind::Impl(Impl {
|
||||
of_trait: Some(trait_ref),
|
||||
of_trait: Some(of_trait),
|
||||
items: [child],
|
||||
self_ty,
|
||||
..
|
||||
}) = item.kind
|
||||
&& !cx.tcx.is_automatically_derived(item.owner_id.to_def_id())
|
||||
&& !item.span.from_expansion()
|
||||
&& let Some(def_id) = trait_ref.trait_def_id()
|
||||
&& let Some(def_id) = of_trait.trait_ref.trait_def_id()
|
||||
&& cx.tcx.is_diagnostic_item(sym::Default, def_id)
|
||||
&& let impl_item_hir = child.hir_id()
|
||||
&& let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir)
|
||||
|
|
|
|||
|
|
@ -201,10 +201,11 @@ declare_lint_pass!(Derive => [
|
|||
impl<'tcx> LateLintPass<'tcx> for Derive {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
if let ItemKind::Impl(Impl {
|
||||
of_trait: Some(trait_ref),
|
||||
of_trait: Some(of_trait),
|
||||
..
|
||||
}) = item.kind
|
||||
{
|
||||
let trait_ref = &of_trait.trait_ref;
|
||||
let ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
|
||||
let is_automatically_derived = cx.tcx.is_automatically_derived(item.owner_id.to_def_id());
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ impl_lint_pass!(DuplicateMod => [DUPLICATE_MOD]);
|
|||
|
||||
impl EarlyLintPass for DuplicateMod {
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
|
||||
if let ItemKind::Mod(_, _, ModKind::Loaded(_, Inline::No, mod_spans, _)) = &item.kind
|
||||
if let ItemKind::Mod(_, _, ModKind::Loaded(_, Inline::No { .. }, mod_spans)) = &item.kind
|
||||
&& let FileName::Real(real) = cx.sess().source_map().span_to_filename(mod_spans.inner_span)
|
||||
&& let Some(local_path) = real.into_local_path()
|
||||
&& let Ok(absolute_path) = local_path.canonicalize()
|
||||
|
|
|
|||
|
|
@ -36,11 +36,11 @@ declare_lint_pass!(EmptyDrop => [EMPTY_DROP]);
|
|||
impl LateLintPass<'_> for EmptyDrop {
|
||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
|
||||
if let ItemKind::Impl(Impl {
|
||||
of_trait: Some(trait_ref),
|
||||
of_trait: Some(of_trait),
|
||||
items: [child],
|
||||
..
|
||||
}) = item.kind
|
||||
&& trait_ref.trait_def_id() == cx.tcx.lang_items().drop_trait()
|
||||
&& of_trait.trait_ref.trait_def_id() == cx.tcx.lang_items().drop_trait()
|
||||
&& let impl_item_hir = child.hir_id()
|
||||
&& let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir)
|
||||
&& let ImplItemKind::Fn(_, b) = &impl_item.kind
|
||||
|
|
|
|||
|
|
@ -442,7 +442,7 @@ impl EmptyLineAfter {
|
|||
None => span.shrink_to_lo(),
|
||||
},
|
||||
mod_items: match kind {
|
||||
ItemKind::Mod(_, _, ModKind::Loaded(items, _, _, _)) => items
|
||||
ItemKind::Mod(_, _, ModKind::Loaded(items, _, _)) => items
|
||||
.iter()
|
||||
.filter(|i| !matches!(i.span.ctxt().outer_expn_data().kind, ExpnKind::AstPass(_)))
|
||||
.map(|i| i.id)
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
|
|||
);
|
||||
},
|
||||
ItemKind::Impl(imp)
|
||||
if let Some(trait_def_id) = imp.of_trait.and_then(|t| t.trait_def_id())
|
||||
if let Some(trait_def_id) = imp.of_trait.and_then(|t| t.trait_ref.trait_def_id())
|
||||
&& let Some(error_def_id) = cx.tcx.get_diagnostic_item(sym::Error)
|
||||
&& error_def_id == trait_def_id
|
||||
&& let Some(def_id) = path_res(cx, imp.self_ty).opt_def_id().and_then(DefId::as_local)
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ impl Visitor<'_> for NestingVisitor<'_, '_> {
|
|||
}
|
||||
|
||||
match &item.kind {
|
||||
ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _, _)) => {
|
||||
ItemKind::Trait(_) | ItemKind::Impl(_) | ItemKind::Mod(.., ModKind::Loaded(_, Inline::Yes, _)) => {
|
||||
self.nest_level += 1;
|
||||
|
||||
if !self.check_indent(item.span, item.id) {
|
||||
|
|
|
|||
|
|
@ -254,10 +254,10 @@ fn is_format_trait_impl(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) -> Optio
|
|||
if impl_item.ident.name == sym::fmt
|
||||
&& let ImplItemKind::Fn(_, body_id) = impl_item.kind
|
||||
&& let Some(Impl {
|
||||
of_trait: Some(trait_ref),
|
||||
of_trait: Some(of_trait),
|
||||
..
|
||||
}) = get_parent_as_impl(cx.tcx, impl_item.hir_id())
|
||||
&& let Some(did) = trait_ref.trait_def_id()
|
||||
&& let Some(did) = of_trait.trait_ref.trait_def_id()
|
||||
&& let Some(name) = cx.tcx.get_diagnostic_name(did)
|
||||
&& matches!(name, sym::Debug | sym::Display)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -67,12 +67,12 @@ impl_lint_pass!(FromOverInto => [FROM_OVER_INTO]);
|
|||
impl<'tcx> LateLintPass<'tcx> for FromOverInto {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
if let ItemKind::Impl(Impl {
|
||||
of_trait: Some(hir_trait_ref),
|
||||
of_trait: Some(of_trait),
|
||||
self_ty,
|
||||
items: [impl_item_ref],
|
||||
..
|
||||
}) = item.kind
|
||||
&& let Some(into_trait_seg) = hir_trait_ref.path.segments.last()
|
||||
&& let Some(into_trait_seg) = of_trait.trait_ref.path.segments.last()
|
||||
// `impl Into<target_ty> for self_ty`
|
||||
&& let Some(GenericArgs { args: [GenericArg::Type(target_ty)], .. }) = into_trait_seg.args
|
||||
&& span_is_local(item.span)
|
||||
|
|
|
|||
|
|
@ -54,8 +54,7 @@ pub(super) fn check_impl_item(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) {
|
|||
if let ImplItemKind::Fn(_, body_id) = impl_item.kind
|
||||
&& let hir::Node::Item(item) = cx.tcx.parent_hir_node(impl_item.hir_id())
|
||||
&& let hir::ItemKind::Impl(impl_) = item.kind
|
||||
&& let hir::Impl { of_trait, .. } = *impl_
|
||||
&& of_trait.is_none()
|
||||
&& let hir::Impl { of_trait: None, .. } = impl_
|
||||
&& let body = cx.tcx.hir_body(body_id)
|
||||
&& cx.tcx.visibility(cx.tcx.hir_body_owner_def_id(body.id())).is_public()
|
||||
&& !is_in_test(cx.tcx, impl_item.hir_id())
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
|
|||
use rustc_errors::{Applicability, MultiSpan};
|
||||
use rustc_hir::def_id::{DefId, DefIdSet};
|
||||
use rustc_hir::hir_id::OwnerId;
|
||||
use rustc_hir::{ImplItem, ImplItemKind, ItemKind, Node, TraitRef};
|
||||
use rustc_hir::{Impl, ImplItem, ImplItemKind, ItemKind, Node, TraitRef};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Ident, kw};
|
||||
|
|
@ -15,10 +15,12 @@ pub(super) fn check_impl_item(cx: &LateContext<'_>, item: &ImplItem<'_>, ignored
|
|||
&& let ImplItemKind::Fn(_, body_id) = item.kind
|
||||
&& let parent_node = cx.tcx.parent_hir_node(item.hir_id())
|
||||
&& let Node::Item(parent_item) = parent_node
|
||||
&& let ItemKind::Impl(impl_) = &parent_item.kind
|
||||
&& let Some(trait_ref) = impl_.of_trait
|
||||
&& let ItemKind::Impl(Impl {
|
||||
of_trait: Some(of_trait),
|
||||
..
|
||||
}) = &parent_item.kind
|
||||
&& let Some(did) = trait_item_def_id_of_impl(cx, item.owner_id)
|
||||
&& !is_from_ignored_trait(&trait_ref, ignored_traits)
|
||||
&& !is_from_ignored_trait(&of_trait.trait_ref, ignored_traits)
|
||||
{
|
||||
let mut param_idents_iter = cx.tcx.hir_body_param_idents(body_id);
|
||||
let mut default_param_idents_iter = cx.tcx.fn_arg_idents(did).iter().copied();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::ty::implements_trait;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::{Item, ItemKind, Path, TraitRef};
|
||||
use rustc_hir::{Item, ItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_session::declare_lint_pass;
|
||||
|
|
@ -76,10 +76,10 @@ impl LateLintPass<'_> for ImplHashWithBorrowStrBytes {
|
|||
/// three of `Hash`, `Borrow<str>` and `Borrow<[u8]>`.
|
||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
|
||||
if let ItemKind::Impl(imp) = item.kind
|
||||
&& let Some(TraitRef {path: Path {span, res, ..}, ..}) = imp.of_trait
|
||||
&& let Some(of_trait) = imp.of_trait
|
||||
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
|
||||
&& let Some(hash_id) = cx.tcx.get_diagnostic_item(sym::Hash)
|
||||
&& Res::Def(DefKind::Trait, hash_id) == *res
|
||||
&& Res::Def(DefKind::Trait, hash_id) == of_trait.trait_ref.path.res
|
||||
&& let Some(borrow_id) = cx.tcx.get_diagnostic_item(sym::Borrow)
|
||||
// since we are in the `Hash` impl, we don't need to check for that.
|
||||
// we need only to check for `Borrow<str>` and `Borrow<[u8]>`
|
||||
|
|
@ -89,7 +89,7 @@ impl LateLintPass<'_> for ImplHashWithBorrowStrBytes {
|
|||
span_lint_and_then(
|
||||
cx,
|
||||
IMPL_HASH_BORROW_WITH_STR_AND_BYTES,
|
||||
*span,
|
||||
of_trait.trait_ref.path.span,
|
||||
"the semantics of `Borrow<T>` around `Hash` can't be satisfied when both `Borrow<str>` and `Borrow<[u8]>` are implemented",
|
||||
|diag| {
|
||||
diag.note("the `Borrow` semantics require that `Hash` must behave the same for all implementations of Borrow<T>");
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@ declare_lint_pass!(InfallibleTryFrom => [INFALLIBLE_TRY_FROM]);
|
|||
impl<'tcx> LateLintPass<'tcx> for InfallibleTryFrom {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
let ItemKind::Impl(imp) = item.kind else { return };
|
||||
let Some(r#trait) = imp.of_trait else { return };
|
||||
let Some(trait_def_id) = r#trait.trait_def_id() else {
|
||||
let Some(of_trait) = imp.of_trait else { return };
|
||||
let Some(trait_def_id) = of_trait.trait_ref.trait_def_id() else {
|
||||
return;
|
||||
};
|
||||
if !cx.tcx.is_diagnostic_item(sym::TryFrom, trait_def_id) {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ use rustc_data_structures::fx::FxHashSet;
|
|||
use rustc_hir::{EnumDef, FieldDef, Item, ItemKind, OwnerId, QPath, TyKind, Variant, VariantData};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::MacroKind;
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
|
@ -503,8 +502,8 @@ impl LateLintPass<'_> for ItemNameRepetitions {
|
|||
);
|
||||
}
|
||||
|
||||
let is_macro_rule = matches!(item.kind, ItemKind::Macro(_, _, MacroKind::Bang));
|
||||
if both_are_public && item_camel.len() > mod_camel.len() && !is_macro_rule {
|
||||
let is_macro = matches!(item.kind, ItemKind::Macro(_, _, _));
|
||||
if both_are_public && item_camel.len() > mod_camel.len() && !is_macro {
|
||||
let matching = count_match_start(mod_camel, &item_camel);
|
||||
let rmatching = count_match_end(mod_camel, &item_camel);
|
||||
let nchars = mod_camel.chars().count();
|
||||
|
|
|
|||
|
|
@ -125,8 +125,9 @@ impl LateLintPass<'_> for IterWithoutIntoIter {
|
|||
fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) {
|
||||
if let ItemKind::Impl(imp) = item.kind
|
||||
&& let TyKind::Ref(_, self_ty_without_ref) = &imp.self_ty.kind
|
||||
&& let Some(trait_ref) = imp.of_trait
|
||||
&& trait_ref
|
||||
&& let Some(of_trait) = imp.of_trait
|
||||
&& of_trait
|
||||
.trait_ref
|
||||
.trait_def_id()
|
||||
.is_some_and(|did| cx.tcx.is_diagnostic_item(sym::IntoIterator, did))
|
||||
&& !item.span.in_external_macro(cx.sess().source_map())
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
|
|||
} = item.kind
|
||||
{
|
||||
check_fn_inner(cx, sig, Some(id), None, generics, item.span, true, self.msrv);
|
||||
} else if let ItemKind::Impl(impl_) = item.kind
|
||||
} else if let ItemKind::Impl(impl_) = &item.kind
|
||||
&& !item.span.from_expansion()
|
||||
{
|
||||
report_extra_impl_lifetimes(cx, impl_);
|
||||
|
|
@ -712,8 +712,8 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
|
|||
let mut checker = LifetimeChecker::<middle_nested_filter::All>::new(cx, impl_.generics);
|
||||
|
||||
walk_generics(&mut checker, impl_.generics);
|
||||
if let Some(ref trait_ref) = impl_.of_trait {
|
||||
walk_trait_ref(&mut checker, trait_ref);
|
||||
if let Some(of_trait) = impl_.of_trait {
|
||||
walk_trait_ref(&mut checker, &of_trait.trait_ref);
|
||||
}
|
||||
walk_unambig_ty(&mut checker, impl_.self_ty);
|
||||
for &item in impl_.items {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_ast::{BinOpKind, LitKind, RangeLimits};
|
|||
use rustc_data_structures::packed::Pu128;
|
||||
use rustc_data_structures::unhash::UnindexMap;
|
||||
use rustc_errors::{Applicability, Diag};
|
||||
use rustc_hir::{Block, Body, Expr, ExprKind, UnOp};
|
||||
use rustc_hir::{Body, Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::source_map::Spanned;
|
||||
|
|
@ -135,12 +135,12 @@ fn assert_len_expr<'hir>(
|
|||
cx: &LateContext<'_>,
|
||||
expr: &'hir Expr<'hir>,
|
||||
) -> Option<(LengthComparison, usize, &'hir Expr<'hir>)> {
|
||||
let (cmp, asserted_len, slice_len) = if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr)
|
||||
&& let ExprKind::Unary(UnOp::Not, condition) = &cond.kind
|
||||
&& let ExprKind::Binary(bin_op, left, right) = &condition.kind
|
||||
let (cmp, asserted_len, slice_len) = if let Some(
|
||||
higher::IfLetOrMatch::Match(cond, [_, then], _)
|
||||
) = higher::IfLetOrMatch::parse(cx, expr)
|
||||
&& let ExprKind::Binary(bin_op, left, right) = &cond.kind
|
||||
// check if `then` block has a never type expression
|
||||
&& let ExprKind::Block(Block { expr: Some(then_expr), .. }, _) = then.kind
|
||||
&& cx.typeck_results().expr_ty(then_expr).is_never()
|
||||
&& cx.typeck_results().expr_ty(then.body).is_never()
|
||||
{
|
||||
len_comparison(bin_op.node, left, right)?
|
||||
} else if let Some((macro_call, bin_op)) = first_node_macro_backtrace(cx, expr).find_map(|macro_call| {
|
||||
|
|
|
|||
|
|
@ -198,8 +198,8 @@ fn check_struct<'tcx>(
|
|||
impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
// is this an `impl Debug for X` block?
|
||||
if let ItemKind::Impl(Impl { of_trait: Some(trait_ref), self_ty, .. }) = item.kind
|
||||
&& let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res
|
||||
if let ItemKind::Impl(Impl { of_trait: Some(of_trait), self_ty, .. }) = item.kind
|
||||
&& let Res::Def(DefKind::Trait, trait_def_id) = of_trait.trait_ref.path.res
|
||||
&& let TyKind::Path(QPath::Resolved(_, self_path)) = &self_ty.kind
|
||||
// make sure that the self type is either a struct, an enum or a union
|
||||
// this prevents ICEs such as when self is a type parameter or a primitive type
|
||||
|
|
|
|||
|
|
@ -190,5 +190,5 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
|
|||
/// and a rustc warning would be triggered, see #15301
|
||||
fn fn_is_externally_exported(cx: &LateContext<'_>, def_id: DefId) -> bool {
|
||||
let attrs = cx.tcx.codegen_fn_attrs(def_id);
|
||||
attrs.contains_extern_indicator()
|
||||
attrs.contains_extern_indicator(cx.tcx, def_id)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,10 +61,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingTraitMethods {
|
|||
if !is_lint_allowed(cx, MISSING_TRAIT_METHODS, item.hir_id())
|
||||
&& span_is_local(item.span)
|
||||
&& let ItemKind::Impl(Impl {
|
||||
of_trait: Some(trait_ref),
|
||||
of_trait: Some(of_trait),
|
||||
..
|
||||
}) = item.kind
|
||||
&& let Some(trait_id) = trait_ref.trait_def_id()
|
||||
&& let Some(trait_id) = of_trait.trait_ref.trait_def_id()
|
||||
{
|
||||
let trait_item_ids: DefIdSet = cx
|
||||
.tcx
|
||||
|
|
|
|||
|
|
@ -778,7 +778,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
|
|||
if let Node::Item(parent_item) = cx.tcx.parent_hir_node(item.hir_id())
|
||||
&& let ItemKind::Impl(impl_block) = parent_item.kind
|
||||
&& let Some(of_trait) = impl_block.of_trait
|
||||
&& let Some(trait_id) = of_trait.trait_def_id()
|
||||
&& let Some(trait_id) = of_trait.trait_ref.trait_def_id()
|
||||
{
|
||||
// Replace all instances of `<Self as Trait>::AssocType` with the
|
||||
// unit type and check again. If the result is the same then the
|
||||
|
|
|
|||
|
|
@ -83,10 +83,10 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy {
|
|||
if !item.span.in_external_macro(cx.tcx.sess.source_map())
|
||||
&& let Some(send_trait) = cx.tcx.get_diagnostic_item(sym::Send)
|
||||
&& let ItemKind::Impl(hir_impl) = &item.kind
|
||||
&& let Some(trait_ref) = &hir_impl.of_trait
|
||||
&& let Some(trait_id) = trait_ref.trait_def_id()
|
||||
&& let Some(of_trait) = &hir_impl.of_trait
|
||||
&& let Some(trait_id) = of_trait.trait_ref.trait_def_id()
|
||||
&& send_trait == trait_id
|
||||
&& hir_impl.polarity == ImplPolarity::Positive
|
||||
&& of_trait.polarity == ImplPolarity::Positive
|
||||
&& let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id)
|
||||
&& let self_ty = ty_trait_ref.instantiate_identity().self_ty()
|
||||
&& let ty::Adt(adt_def, impl_trait_args) = self_ty.kind()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::msrvs::Msrv;
|
||||
use clippy_utils::qualify_min_const_fn::is_stable_const_fn;
|
||||
use clippy_utils::source::SpanRangeExt;
|
||||
use clippy_utils::ty::implements_trait;
|
||||
use clippy_utils::visitors::for_each_expr_without_closures;
|
||||
|
|
@ -21,7 +20,7 @@ pub(super) fn check<'tcx>(
|
|||
expr: &'tcx hir::Expr<'_>,
|
||||
assignee: &'tcx hir::Expr<'_>,
|
||||
e: &'tcx hir::Expr<'_>,
|
||||
msrv: Msrv,
|
||||
_msrv: Msrv,
|
||||
) {
|
||||
if let hir::ExprKind::Binary(op, l, r) = &e.kind {
|
||||
let lint = |assignee: &hir::Expr<'_>, rhs: &hir::Expr<'_>| {
|
||||
|
|
@ -45,10 +44,8 @@ pub(super) fn check<'tcx>(
|
|||
}
|
||||
|
||||
// Skip if the trait is not stable in const contexts
|
||||
if is_in_const_context(cx)
|
||||
&& let Some(binop_id) = cx.tcx.associated_item_def_ids(trait_id).first()
|
||||
&& !is_stable_const_fn(cx, *binop_id, msrv)
|
||||
{
|
||||
// FIXME: reintroduce a better check after this is merged back into Clippy
|
||||
if is_in_const_context(cx) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ fn in_impl<'tcx>(
|
|||
&& let item = cx.tcx.hir_expect_item(impl_def_id.expect_local())
|
||||
&& let ItemKind::Impl(item) = &item.kind
|
||||
&& let Some(of_trait) = &item.of_trait
|
||||
&& let Some(seg) = of_trait.path.segments.last()
|
||||
&& let Some(seg) = of_trait.trait_ref.path.segments.last()
|
||||
&& let Res::Def(_, trait_id) = seg.res
|
||||
&& trait_id == bin_op
|
||||
&& let Some(generic_args) = seg.args
|
||||
|
|
|
|||
|
|
@ -34,15 +34,15 @@ declare_lint_pass!(PartialEqNeImpl => [PARTIALEQ_NE_IMPL]);
|
|||
impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
if let ItemKind::Impl(Impl {
|
||||
of_trait: Some(trait_ref),
|
||||
of_trait: Some(of_trait),
|
||||
items: impl_items,
|
||||
..
|
||||
}) = item.kind
|
||||
&& !cx.tcx.is_automatically_derived(item.owner_id.to_def_id())
|
||||
&& let Some(eq_trait) = cx.tcx.lang_items().eq_trait()
|
||||
&& trait_ref.path.res.def_id() == eq_trait
|
||||
&& of_trait.trait_ref.path.res.def_id() == eq_trait
|
||||
{
|
||||
for impl_item in *impl_items {
|
||||
for impl_item in impl_items {
|
||||
if cx.tcx.item_name(impl_item.owner_id) == sym::ne {
|
||||
span_lint_hir(
|
||||
cx,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ use rustc_lint::{LateContext, LateLintPass};
|
|||
use rustc_middle::ty;
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::def_id::CRATE_DEF_ID;
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -89,8 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
|
|||
// We ignore macro exports. And `ListStem` uses, which aren't interesting.
|
||||
fn is_ignorable_export<'tcx>(item: &'tcx Item<'tcx>) -> bool {
|
||||
if let ItemKind::Use(path, kind) = item.kind {
|
||||
let ignore = matches!(path.res.macro_ns, Some(Res::Def(DefKind::Macro(MacroKind::Bang), _)))
|
||||
|| kind == UseKind::ListStem;
|
||||
let ignore = matches!(path.res.macro_ns, Some(Res::Def(DefKind::Macro(_), _))) || kind == UseKind::ListStem;
|
||||
if ignore {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,9 +68,9 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
|
|||
let existing_name = map.get_mut(res).unwrap();
|
||||
|
||||
match of_trait {
|
||||
Some(trait_ref) => {
|
||||
Some(of_trait) => {
|
||||
let mut methods_in_trait: BTreeSet<Symbol> = if let Node::TraitRef(TraitRef { path, .. }) =
|
||||
cx.tcx.hir_node(trait_ref.hir_ref_id)
|
||||
cx.tcx.hir_node(of_trait.trait_ref.hir_ref_id)
|
||||
&& let Res::Def(DefKind::Trait, did) = path.res
|
||||
{
|
||||
// FIXME: if
|
||||
|
|
|
|||
|
|
@ -26,16 +26,16 @@ declare_lint_pass!(SerdeApi => [SERDE_API_MISUSE]);
|
|||
impl<'tcx> LateLintPass<'tcx> for SerdeApi {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
if let ItemKind::Impl(Impl {
|
||||
of_trait: Some(trait_ref),
|
||||
of_trait: Some(of_trait),
|
||||
items,
|
||||
..
|
||||
}) = item.kind
|
||||
{
|
||||
let did = trait_ref.path.res.def_id();
|
||||
let did = of_trait.trait_ref.path.res.def_id();
|
||||
if paths::SERDE_DE_VISITOR.matches(cx, did) {
|
||||
let mut seen_str = None;
|
||||
let mut seen_string = None;
|
||||
for item in *items {
|
||||
for item in items {
|
||||
match cx.tcx.item_name(item.owner_id) {
|
||||
sym::visit_str => seen_str = Some(cx.tcx.def_span(item.owner_id)),
|
||||
sym::visit_string => seen_string = Some(cx.tcx.def_span(item.owner_id)),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
|
||||
use rustc_ast::node_id::{NodeId, NodeMap};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::visit::{Visitor, walk_expr};
|
||||
use rustc_ast::{Crate, Expr, ExprKind, Item, ItemKind, MacroDef, ModKind, Ty, TyKind, UseTreeKind};
|
||||
use rustc_errors::Applicability;
|
||||
|
|
@ -124,7 +123,7 @@ impl Visitor<'_> for ImportUsageVisitor {
|
|||
}
|
||||
|
||||
impl SingleComponentPathImports {
|
||||
fn check_mod(&mut self, items: &[P<Item>]) {
|
||||
fn check_mod(&mut self, items: &[Box<Item>]) {
|
||||
// keep track of imports reused with `self` keyword, such as `self::crypto_hash` in the example
|
||||
// below. Removing the `use crypto_hash;` would make this a compile error
|
||||
// ```
|
||||
|
|
|
|||
|
|
@ -48,10 +48,10 @@ declare_lint_pass!(ToStringTraitImpl => [TO_STRING_TRAIT_IMPL]);
|
|||
impl<'tcx> LateLintPass<'tcx> for ToStringTraitImpl {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx Item<'tcx>) {
|
||||
if let ItemKind::Impl(Impl {
|
||||
of_trait: Some(trait_ref),
|
||||
of_trait: Some(of_trait),
|
||||
..
|
||||
}) = it.kind
|
||||
&& let Some(trait_did) = trait_ref.trait_def_id()
|
||||
&& let Some(trait_did) = of_trait.trait_ref.trait_def_id()
|
||||
&& cx.tcx.is_diagnostic_item(sym::ToString, trait_did)
|
||||
{
|
||||
span_lint_and_help(
|
||||
|
|
|
|||
|
|
@ -137,9 +137,9 @@ fn get_impl_trait_def_id(cx: &LateContext<'_>, method_def_id: LocalDefId) -> Opt
|
|||
// We exclude `impl` blocks generated from rustc's proc macros.
|
||||
&& !cx.tcx.is_automatically_derived(owner_id.to_def_id())
|
||||
// It is a implementation of a trait.
|
||||
&& let Some(trait_) = impl_.of_trait
|
||||
&& let Some(of_trait) = impl_.of_trait
|
||||
{
|
||||
trait_.trait_def_id()
|
||||
of_trait.trait_ref.trait_def_id()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -242,8 +242,8 @@ fn check_to_string(cx: &LateContext<'_>, method_span: Span, method_def_id: Local
|
|||
// We exclude `impl` blocks generated from rustc's proc macros.
|
||||
&& !cx.tcx.is_automatically_derived(owner_id.to_def_id())
|
||||
// It is a implementation of a trait.
|
||||
&& let Some(trait_) = impl_.of_trait
|
||||
&& let Some(trait_def_id) = trait_.trait_def_id()
|
||||
&& let Some(of_trait) = impl_.of_trait
|
||||
&& let Some(trait_def_id) = of_trait.trait_ref.trait_def_id()
|
||||
// The trait is `ToString`.
|
||||
&& cx.tcx.is_diagnostic_item(sym::ToString, trait_def_id)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use clippy_utils::source::walk_span_to_context;
|
|||
use clippy_utils::visitors::{Descend, for_each_expr};
|
||||
use hir::HirId;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{Block, BlockCheckMode, ItemKind, Node, UnsafeSource};
|
||||
use rustc_hir::{Block, BlockCheckMode, Impl, ItemKind, Node, UnsafeSource};
|
||||
use rustc_lexer::{FrontmatterAllowed, TokenKind, tokenize};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_session::impl_lint_pass;
|
||||
|
|
@ -202,79 +202,41 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
|
|||
};
|
||||
|
||||
let item_has_safety_comment = item_has_safety_comment(cx, item);
|
||||
match (&item.kind, item_has_safety_comment) {
|
||||
// lint unsafe impl without safety comment
|
||||
(ItemKind::Impl(impl_), HasSafetyComment::No) if impl_.safety.is_unsafe() => {
|
||||
if !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, item.hir_id())
|
||||
&& !is_unsafe_from_proc_macro(cx, item.span)
|
||||
{
|
||||
let source_map = cx.tcx.sess.source_map();
|
||||
let span = if source_map.is_multiline(item.span) {
|
||||
source_map.span_until_char(item.span, '\n')
|
||||
} else {
|
||||
item.span
|
||||
};
|
||||
|
||||
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
UNDOCUMENTED_UNSAFE_BLOCKS,
|
||||
span,
|
||||
"unsafe impl missing a safety comment",
|
||||
|diag| {
|
||||
diag.help("consider adding a safety comment on the preceding line");
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
// lint safe impl with unnecessary safety comment
|
||||
(ItemKind::Impl(impl_), HasSafetyComment::Yes(pos)) if impl_.safety.is_safe() => {
|
||||
if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, item.hir_id()) {
|
||||
let (span, help_span) = mk_spans(pos);
|
||||
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
UNNECESSARY_SAFETY_COMMENT,
|
||||
span,
|
||||
"impl has unnecessary safety comment",
|
||||
|diag| {
|
||||
diag.span_help(help_span, "consider removing the safety comment");
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
(ItemKind::Impl(_), _) => {},
|
||||
// const and static items only need a safety comment if their body is an unsafe block, lint otherwise
|
||||
(&ItemKind::Const(.., body) | &ItemKind::Static(.., body), HasSafetyComment::Yes(pos)) => {
|
||||
if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, body.hir_id) {
|
||||
let body = cx.tcx.hir_body(body);
|
||||
if !matches!(
|
||||
body.value.kind, hir::ExprKind::Block(block, _)
|
||||
if block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided)
|
||||
) {
|
||||
let (span, help_span) = mk_spans(pos);
|
||||
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
UNNECESSARY_SAFETY_COMMENT,
|
||||
span,
|
||||
format!(
|
||||
"{} has unnecessary safety comment",
|
||||
cx.tcx.def_descr(item.owner_id.to_def_id()),
|
||||
),
|
||||
|diag| {
|
||||
diag.span_help(help_span, "consider removing the safety comment");
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
// Aside from unsafe impls and consts/statics with an unsafe block, items in general
|
||||
// do not have safety invariants that need to be documented, so lint those.
|
||||
(_, HasSafetyComment::Yes(pos)) => {
|
||||
if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, item.hir_id()) {
|
||||
let (span, help_span) = mk_spans(pos);
|
||||
match item_has_safety_comment {
|
||||
HasSafetyComment::Yes(pos) => check_has_safety_comment(cx, item, mk_spans(pos)),
|
||||
HasSafetyComment::No => check_has_no_safety_comment(cx, item),
|
||||
HasSafetyComment::Maybe => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_has_safety_comment(cx: &LateContext<'_>, item: &hir::Item<'_>, (span, help_span): (Span, Span)) {
|
||||
match &item.kind {
|
||||
ItemKind::Impl(Impl {
|
||||
of_trait: Some(of_trait),
|
||||
..
|
||||
}) if of_trait.safety.is_safe() => {
|
||||
if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, item.hir_id()) {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
UNNECESSARY_SAFETY_COMMENT,
|
||||
span,
|
||||
"impl has unnecessary safety comment",
|
||||
|diag| {
|
||||
diag.span_help(help_span, "consider removing the safety comment");
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
ItemKind::Impl(_) => {},
|
||||
// const and static items only need a safety comment if their body is an unsafe block, lint otherwise
|
||||
&ItemKind::Const(.., body) | &ItemKind::Static(.., body) => {
|
||||
if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, body.hir_id) {
|
||||
let body = cx.tcx.hir_body(body);
|
||||
if !matches!(
|
||||
body.value.kind, hir::ExprKind::Block(block, _)
|
||||
if block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided)
|
||||
) {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
UNNECESSARY_SAFETY_COMMENT,
|
||||
|
|
@ -288,12 +250,56 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
|
|||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
},
|
||||
// Aside from unsafe impls and consts/statics with an unsafe block, items in general
|
||||
// do not have safety invariants that need to be documented, so lint those.
|
||||
_ => {
|
||||
if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, item.hir_id()) {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
UNNECESSARY_SAFETY_COMMENT,
|
||||
span,
|
||||
format!(
|
||||
"{} has unnecessary safety comment",
|
||||
cx.tcx.def_descr(item.owner_id.to_def_id()),
|
||||
),
|
||||
|diag| {
|
||||
diag.span_help(help_span, "consider removing the safety comment");
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
fn check_has_no_safety_comment(cx: &LateContext<'_>, item: &hir::Item<'_>) {
|
||||
if let ItemKind::Impl(Impl {
|
||||
of_trait: Some(of_trait),
|
||||
..
|
||||
}) = item.kind
|
||||
&& of_trait.safety.is_unsafe()
|
||||
&& !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, item.hir_id())
|
||||
&& !is_unsafe_from_proc_macro(cx, item.span)
|
||||
{
|
||||
let source_map = cx.tcx.sess.source_map();
|
||||
let span = if source_map.is_multiline(item.span) {
|
||||
source_map.span_until_char(item.span, '\n')
|
||||
} else {
|
||||
item.span
|
||||
};
|
||||
|
||||
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
UNDOCUMENTED_UNSAFE_BLOCKS,
|
||||
span,
|
||||
"unsafe impl missing a safety comment",
|
||||
|diag| {
|
||||
diag.help("consider adding a safety comment on the preceding line");
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
fn expr_has_unnecessary_safety_comment<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
|
|
|
|||
|
|
@ -7,13 +7,14 @@ use clippy_utils::msrvs::{self, MsrvStack};
|
|||
use clippy_utils::over;
|
||||
use rustc_ast::PatKind::*;
|
||||
use rustc_ast::mut_visit::*;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, DUMMY_NODE_ID, Mutability, Pat, PatKind};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::DUMMY_SP;
|
||||
// import needed to shadow `PatKind::Box` glob-imported above
|
||||
use std::boxed::Box;
|
||||
use std::cell::Cell;
|
||||
use std::mem;
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
|
@ -97,7 +98,7 @@ fn lint_unnested_or_patterns(cx: &EarlyContext<'_>, pat: &Pat) {
|
|||
return;
|
||||
}
|
||||
|
||||
let mut pat = P(pat.clone());
|
||||
let mut pat = Box::new(pat.clone());
|
||||
|
||||
// Nix all the paren patterns everywhere so that they aren't in our way.
|
||||
remove_all_parens(&mut pat);
|
||||
|
|
@ -119,7 +120,7 @@ fn lint_unnested_or_patterns(cx: &EarlyContext<'_>, pat: &Pat) {
|
|||
}
|
||||
|
||||
/// Remove all `(p)` patterns in `pat`.
|
||||
fn remove_all_parens(pat: &mut P<Pat>) {
|
||||
fn remove_all_parens(pat: &mut Box<Pat>) {
|
||||
#[derive(Default)]
|
||||
struct Visitor {
|
||||
/// If is not in the outer most pattern. This is needed to avoid removing the outermost
|
||||
|
|
@ -142,7 +143,7 @@ fn remove_all_parens(pat: &mut P<Pat>) {
|
|||
}
|
||||
|
||||
/// Insert parens where necessary according to Rust's precedence rules for patterns.
|
||||
fn insert_necessary_parens(pat: &mut P<Pat>) {
|
||||
fn insert_necessary_parens(pat: &mut Box<Pat>) {
|
||||
struct Visitor;
|
||||
impl MutVisitor for Visitor {
|
||||
fn visit_pat(&mut self, pat: &mut Pat) {
|
||||
|
|
@ -154,7 +155,7 @@ fn insert_necessary_parens(pat: &mut P<Pat>) {
|
|||
Ref(p, Mutability::Not) if matches!(p.kind, Ident(BindingMode::MUT, ..)) => p, // `&(mut x)`
|
||||
_ => return,
|
||||
};
|
||||
target.kind = Paren(P(take_pat(target)));
|
||||
target.kind = Paren(Box::new(take_pat(target)));
|
||||
}
|
||||
}
|
||||
Visitor.visit_pat(pat);
|
||||
|
|
@ -162,7 +163,7 @@ fn insert_necessary_parens(pat: &mut P<Pat>) {
|
|||
|
||||
/// Unnest or-patterns `p0 | ... | p1` in the pattern `pat`.
|
||||
/// For example, this would transform `Some(0) | FOO | Some(2)` into `Some(0 | 2) | FOO`.
|
||||
fn unnest_or_patterns(pat: &mut P<Pat>) -> bool {
|
||||
fn unnest_or_patterns(pat: &mut Box<Pat>) -> bool {
|
||||
struct Visitor {
|
||||
changed: bool,
|
||||
}
|
||||
|
|
@ -222,7 +223,7 @@ macro_rules! always_pat {
|
|||
/// Focus on `focus_idx` in `alternatives`,
|
||||
/// attempting to extend it with elements of the same constructor `C`
|
||||
/// in `alternatives[focus_idx + 1..]`.
|
||||
fn transform_with_focus_on_idx(alternatives: &mut ThinVec<P<Pat>>, focus_idx: usize) -> bool {
|
||||
fn transform_with_focus_on_idx(alternatives: &mut ThinVec<Box<Pat>>, focus_idx: usize) -> bool {
|
||||
// Extract the kind; we'll need to make some changes in it.
|
||||
let mut focus_kind = mem::replace(&mut alternatives[focus_idx].kind, Wild);
|
||||
// We'll focus on `alternatives[focus_idx]`,
|
||||
|
|
@ -283,14 +284,14 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec<P<Pat>>, focus_idx: us
|
|||
|k, ps1, idx| matches!(
|
||||
k,
|
||||
TupleStruct(qself2, path2, ps2)
|
||||
if eq_maybe_qself(qself1.as_ref(), qself2.as_ref())
|
||||
if eq_maybe_qself(qself1.as_deref(), qself2.as_deref())
|
||||
&& eq_path(path1, path2) && eq_pre_post(ps1, ps2, idx)
|
||||
),
|
||||
|k| always_pat!(k, TupleStruct(_, _, ps) => ps),
|
||||
),
|
||||
// Transform a record pattern `S { fp_0, ..., fp_n }`.
|
||||
Struct(qself1, path1, fps1, rest1) => {
|
||||
extend_with_struct_pat(qself1.as_ref(), path1, fps1, *rest1, start, alternatives)
|
||||
extend_with_struct_pat(qself1.as_deref(), path1, fps1, *rest1, start, alternatives)
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -303,12 +304,12 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec<P<Pat>>, focus_idx: us
|
|||
/// So when we fixate on some `ident_k: pat_k`, we try to find `ident_k` in the other pattern
|
||||
/// and check that all `fp_i` where `i ∈ ((0...n) \ k)` between two patterns are equal.
|
||||
fn extend_with_struct_pat(
|
||||
qself1: Option<&P<ast::QSelf>>,
|
||||
qself1: Option<&ast::QSelf>,
|
||||
path1: &ast::Path,
|
||||
fps1: &mut [ast::PatField],
|
||||
rest1: ast::PatFieldsRest,
|
||||
start: usize,
|
||||
alternatives: &mut ThinVec<P<Pat>>,
|
||||
alternatives: &mut ThinVec<Box<Pat>>,
|
||||
) -> bool {
|
||||
(0..fps1.len()).any(|idx| {
|
||||
let pos_in_2 = Cell::new(None); // The element `k`.
|
||||
|
|
@ -318,7 +319,7 @@ fn extend_with_struct_pat(
|
|||
|k| {
|
||||
matches!(k, Struct(qself2, path2, fps2, rest2)
|
||||
if rest1 == *rest2 // If one struct pattern has `..` so must the other.
|
||||
&& eq_maybe_qself(qself1, qself2.as_ref())
|
||||
&& eq_maybe_qself(qself1, qself2.as_deref())
|
||||
&& eq_path(path1, path2)
|
||||
&& fps1.len() == fps2.len()
|
||||
&& fps1.iter().enumerate().all(|(idx_1, fp1)| {
|
||||
|
|
@ -346,11 +347,11 @@ fn extend_with_struct_pat(
|
|||
/// while also requiring `ps1[..n] ~ ps2[..n]` (pre) and `ps1[n + 1..] ~ ps2[n + 1..]` (post),
|
||||
/// where `~` denotes semantic equality.
|
||||
fn extend_with_matching_product(
|
||||
targets: &mut [P<Pat>],
|
||||
targets: &mut [Box<Pat>],
|
||||
start: usize,
|
||||
alternatives: &mut ThinVec<P<Pat>>,
|
||||
predicate: impl Fn(&PatKind, &[P<Pat>], usize) -> bool,
|
||||
extract: impl Fn(PatKind) -> ThinVec<P<Pat>>,
|
||||
alternatives: &mut ThinVec<Box<Pat>>,
|
||||
predicate: impl Fn(&PatKind, &[Box<Pat>], usize) -> bool,
|
||||
extract: impl Fn(PatKind) -> ThinVec<Box<Pat>>,
|
||||
) -> bool {
|
||||
(0..targets.len()).any(|idx| {
|
||||
let tail_or = drain_matching(
|
||||
|
|
@ -377,14 +378,14 @@ fn take_pat(from: &mut Pat) -> Pat {
|
|||
|
||||
/// Extend `target` as an or-pattern with the alternatives
|
||||
/// in `tail_or` if there are any and return if there were.
|
||||
fn extend_with_tail_or(target: &mut Pat, tail_or: ThinVec<P<Pat>>) -> bool {
|
||||
fn extend(target: &mut Pat, mut tail_or: ThinVec<P<Pat>>) {
|
||||
fn extend_with_tail_or(target: &mut Pat, tail_or: ThinVec<Box<Pat>>) -> bool {
|
||||
fn extend(target: &mut Pat, mut tail_or: ThinVec<Box<Pat>>) {
|
||||
match target {
|
||||
// On an existing or-pattern in the target, append to it.
|
||||
Pat { kind: Or(ps), .. } => ps.append(&mut tail_or),
|
||||
// Otherwise convert the target to an or-pattern.
|
||||
target => {
|
||||
let mut init_or = thin_vec![P(take_pat(target))];
|
||||
let mut init_or = thin_vec![Box::new(take_pat(target))];
|
||||
init_or.append(&mut tail_or);
|
||||
target.kind = Or(init_or);
|
||||
},
|
||||
|
|
@ -403,10 +404,10 @@ fn extend_with_tail_or(target: &mut Pat, tail_or: ThinVec<P<Pat>>) -> bool {
|
|||
// Only elements beginning with `start` are considered for extraction.
|
||||
fn drain_matching(
|
||||
start: usize,
|
||||
alternatives: &mut ThinVec<P<Pat>>,
|
||||
alternatives: &mut ThinVec<Box<Pat>>,
|
||||
predicate: impl Fn(&PatKind) -> bool,
|
||||
extract: impl Fn(PatKind) -> P<Pat>,
|
||||
) -> ThinVec<P<Pat>> {
|
||||
extract: impl Fn(PatKind) -> Box<Pat>,
|
||||
) -> ThinVec<Box<Pat>> {
|
||||
let mut tail_or = ThinVec::new();
|
||||
let mut idx = 0;
|
||||
|
||||
|
|
@ -438,15 +439,15 @@ fn drain_matching(
|
|||
fn extend_with_matching(
|
||||
target: &mut Pat,
|
||||
start: usize,
|
||||
alternatives: &mut ThinVec<P<Pat>>,
|
||||
alternatives: &mut ThinVec<Box<Pat>>,
|
||||
predicate: impl Fn(&PatKind) -> bool,
|
||||
extract: impl Fn(PatKind) -> P<Pat>,
|
||||
extract: impl Fn(PatKind) -> Box<Pat>,
|
||||
) -> bool {
|
||||
extend_with_tail_or(target, drain_matching(start, alternatives, predicate, extract))
|
||||
}
|
||||
|
||||
/// Are the patterns in `ps1` and `ps2` equal save for `ps1[idx]` compared to `ps2[idx]`?
|
||||
fn eq_pre_post(ps1: &[P<Pat>], ps2: &[P<Pat>], idx: usize) -> bool {
|
||||
fn eq_pre_post(ps1: &[Box<Pat>], ps2: &[Box<Pat>], idx: usize) -> bool {
|
||||
ps1.len() == ps2.len()
|
||||
&& ps1[idx].is_rest() == ps2[idx].is_rest() // Avoid `[x, ..] | [x, 0]` => `[x, .. | 0]`.
|
||||
&& over(&ps1[..idx], &ps2[..idx], |l, r| eq_pat(l, r))
|
||||
|
|
|
|||
|
|
@ -347,10 +347,10 @@ impl<'tcx> LateLintPass<'tcx> for Write {
|
|||
|
||||
fn is_debug_impl(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
|
||||
if let ItemKind::Impl(Impl {
|
||||
of_trait: Some(trait_ref),
|
||||
of_trait: Some(of_trait),
|
||||
..
|
||||
}) = &item.kind
|
||||
&& let Some(trait_id) = trait_ref.trait_def_id()
|
||||
&& let Some(trait_id) = of_trait.trait_ref.trait_def_id()
|
||||
{
|
||||
cx.tcx.is_diagnostic_item(sym::Debug, trait_id)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ use rustc_hir::attrs::AttributeKind;
|
|||
use rustc_hir::def::Res;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::{
|
||||
AttrArgs, AttrItem, AttrPath, Attribute, HirId, Impl, Item, ItemKind, Path, QPath, TraitRef, Ty, TyKind, find_attr,
|
||||
AttrArgs, AttrItem, AttrPath, Attribute, HirId, Impl, Item, ItemKind, Path, QPath, TraitImplHeader, TraitRef, Ty,
|
||||
TyKind, find_attr,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_lint_defs::declare_tool_lint;
|
||||
|
|
@ -56,10 +57,14 @@ impl<'tcx> LateLintPass<'tcx> for DeriveDeserializeAllowingUnknown {
|
|||
// Is this an `impl` (of a certain form)?
|
||||
let ItemKind::Impl(Impl {
|
||||
of_trait:
|
||||
Some(TraitRef {
|
||||
path:
|
||||
Path {
|
||||
res: Res::Def(_, trait_def_id),
|
||||
Some(TraitImplHeader {
|
||||
trait_ref:
|
||||
TraitRef {
|
||||
path:
|
||||
Path {
|
||||
res: Res::Def(_, trait_def_id),
|
||||
..
|
||||
},
|
||||
..
|
||||
},
|
||||
..
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain:
|
|||
|
||||
<!-- begin autogenerated nightly -->
|
||||
```
|
||||
nightly-2025-08-07
|
||||
nightly-2025-08-22
|
||||
```
|
||||
<!-- end autogenerated nightly -->
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
#![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
|
||||
|
||||
use crate::{both, over};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, *};
|
||||
use rustc_span::symbol::Ident;
|
||||
use std::mem;
|
||||
|
|
@ -42,21 +41,23 @@ pub fn eq_pat(l: &Pat, r: &Pat) -> bool {
|
|||
b1 == b2 && eq_id(*i1, *i2) && both(s1.as_deref(), s2.as_deref(), eq_pat)
|
||||
},
|
||||
(Range(lf, lt, le), Range(rf, rt, re)) => {
|
||||
eq_expr_opt(lf.as_ref(), rf.as_ref())
|
||||
&& eq_expr_opt(lt.as_ref(), rt.as_ref())
|
||||
eq_expr_opt(lf.as_deref(), rf.as_deref())
|
||||
&& eq_expr_opt(lt.as_deref(), rt.as_deref())
|
||||
&& eq_range_end(&le.node, &re.node)
|
||||
},
|
||||
(Box(l), Box(r))
|
||||
| (Ref(l, Mutability::Not), Ref(r, Mutability::Not))
|
||||
| (Ref(l, Mutability::Mut), Ref(r, Mutability::Mut)) => eq_pat(l, r),
|
||||
(Tuple(l), Tuple(r)) | (Slice(l), Slice(r)) => over(l, r, |l, r| eq_pat(l, r)),
|
||||
(Path(lq, lp), Path(rq, rp)) => both(lq.as_ref(), rq.as_ref(), eq_qself) && eq_path(lp, rp),
|
||||
(Path(lq, lp), Path(rq, rp)) => both(lq.as_deref(), rq.as_deref(), eq_qself) && eq_path(lp, rp),
|
||||
(TupleStruct(lqself, lp, lfs), TupleStruct(rqself, rp, rfs)) => {
|
||||
eq_maybe_qself(lqself.as_ref(), rqself.as_ref()) && eq_path(lp, rp) && over(lfs, rfs, |l, r| eq_pat(l, r))
|
||||
eq_maybe_qself(lqself.as_deref(), rqself.as_deref())
|
||||
&& eq_path(lp, rp)
|
||||
&& over(lfs, rfs, |l, r| eq_pat(l, r))
|
||||
},
|
||||
(Struct(lqself, lp, lfs, lr), Struct(rqself, rp, rfs, rr)) => {
|
||||
lr == rr
|
||||
&& eq_maybe_qself(lqself.as_ref(), rqself.as_ref())
|
||||
&& eq_maybe_qself(lqself.as_deref(), rqself.as_deref())
|
||||
&& eq_path(lp, rp)
|
||||
&& unordered_over(lfs, rfs, eq_field_pat)
|
||||
},
|
||||
|
|
@ -83,11 +84,11 @@ pub fn eq_field_pat(l: &PatField, r: &PatField) -> bool {
|
|||
&& over(&l.attrs, &r.attrs, eq_attr)
|
||||
}
|
||||
|
||||
pub fn eq_qself(l: &P<QSelf>, r: &P<QSelf>) -> bool {
|
||||
pub fn eq_qself(l: &QSelf, r: &QSelf) -> bool {
|
||||
l.position == r.position && eq_ty(&l.ty, &r.ty)
|
||||
}
|
||||
|
||||
pub fn eq_maybe_qself(l: Option<&P<QSelf>>, r: Option<&P<QSelf>>) -> bool {
|
||||
pub fn eq_maybe_qself(l: Option<&QSelf>, r: Option<&QSelf>) -> bool {
|
||||
match (l, r) {
|
||||
(Some(l), Some(r)) => eq_qself(l, r),
|
||||
(None, None) => true,
|
||||
|
|
@ -130,8 +131,8 @@ pub fn eq_generic_arg(l: &GenericArg, r: &GenericArg) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn eq_expr_opt(l: Option<&P<Expr>>, r: Option<&P<Expr>>) -> bool {
|
||||
both(l, r, |l, r| eq_expr(l, r))
|
||||
pub fn eq_expr_opt(l: Option<&Expr>, r: Option<&Expr>) -> bool {
|
||||
both(l, r, eq_expr)
|
||||
}
|
||||
|
||||
pub fn eq_struct_rest(l: &StructRest, r: &StructRest) -> bool {
|
||||
|
|
@ -178,7 +179,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
|
|||
(Cast(l, lt), Cast(r, rt)) | (Type(l, lt), Type(r, rt)) => eq_expr(l, r) && eq_ty(lt, rt),
|
||||
(Let(lp, le, _, _), Let(rp, re, _, _)) => eq_pat(lp, rp) && eq_expr(le, re),
|
||||
(If(lc, lt, le), If(rc, rt, re)) => {
|
||||
eq_expr(lc, rc) && eq_block(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref())
|
||||
eq_expr(lc, rc) && eq_block(lt, rt) && eq_expr_opt(le.as_deref(), re.as_deref())
|
||||
},
|
||||
(While(lc, lt, ll), While(rc, rt, rl)) => {
|
||||
eq_label(ll.as_ref(), rl.as_ref()) && eq_expr(lc, rc) && eq_block(lt, rt)
|
||||
|
|
@ -202,9 +203,11 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
|
|||
(Loop(lt, ll, _), Loop(rt, rl, _)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_block(lt, rt),
|
||||
(Block(lb, ll), Block(rb, rl)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_block(lb, rb),
|
||||
(TryBlock(l), TryBlock(r)) => eq_block(l, r),
|
||||
(Yield(l), Yield(r)) => eq_expr_opt(l.expr(), r.expr()) && l.same_kind(r),
|
||||
(Ret(l), Ret(r)) => eq_expr_opt(l.as_ref(), r.as_ref()),
|
||||
(Break(ll, le), Break(rl, re)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_expr_opt(le.as_ref(), re.as_ref()),
|
||||
(Yield(l), Yield(r)) => eq_expr_opt(l.expr().map(Box::as_ref), r.expr().map(Box::as_ref)) && l.same_kind(r),
|
||||
(Ret(l), Ret(r)) => eq_expr_opt(l.as_deref(), r.as_deref()),
|
||||
(Break(ll, le), Break(rl, re)) => {
|
||||
eq_label(ll.as_ref(), rl.as_ref()) && eq_expr_opt(le.as_deref(), re.as_deref())
|
||||
},
|
||||
(Continue(ll), Continue(rl)) => eq_label(ll.as_ref(), rl.as_ref()),
|
||||
(Assign(l1, l2, _), Assign(r1, r2, _)) | (Index(l1, l2, _), Index(r1, r2, _)) => {
|
||||
eq_expr(l1, r1) && eq_expr(l2, r2)
|
||||
|
|
@ -241,13 +244,13 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
|
|||
},
|
||||
(Gen(lc, lb, lk, _), Gen(rc, rb, rk, _)) => lc == rc && eq_block(lb, rb) && lk == rk,
|
||||
(Range(lf, lt, ll), Range(rf, rt, rl)) => {
|
||||
ll == rl && eq_expr_opt(lf.as_ref(), rf.as_ref()) && eq_expr_opt(lt.as_ref(), rt.as_ref())
|
||||
ll == rl && eq_expr_opt(lf.as_deref(), rf.as_deref()) && eq_expr_opt(lt.as_deref(), rt.as_deref())
|
||||
},
|
||||
(AddrOf(lbk, lm, le), AddrOf(rbk, rm, re)) => lbk == rbk && lm == rm && eq_expr(le, re),
|
||||
(Path(lq, lp), Path(rq, rp)) => both(lq.as_ref(), rq.as_ref(), eq_qself) && eq_path(lp, rp),
|
||||
(Path(lq, lp), Path(rq, rp)) => both(lq.as_deref(), rq.as_deref(), eq_qself) && eq_path(lp, rp),
|
||||
(MacCall(l), MacCall(r)) => eq_mac_call(l, r),
|
||||
(Struct(lse), Struct(rse)) => {
|
||||
eq_maybe_qself(lse.qself.as_ref(), rse.qself.as_ref())
|
||||
eq_maybe_qself(lse.qself.as_deref(), rse.qself.as_deref())
|
||||
&& eq_path(&lse.path, &rse.path)
|
||||
&& eq_struct_rest(&lse.rest, &rse.rest)
|
||||
&& unordered_over(&lse.fields, &rse.fields, eq_field)
|
||||
|
|
@ -279,8 +282,8 @@ pub fn eq_field(l: &ExprField, r: &ExprField) -> bool {
|
|||
pub fn eq_arm(l: &Arm, r: &Arm) -> bool {
|
||||
l.is_placeholder == r.is_placeholder
|
||||
&& eq_pat(&l.pat, &r.pat)
|
||||
&& eq_expr_opt(l.body.as_ref(), r.body.as_ref())
|
||||
&& eq_expr_opt(l.guard.as_ref(), r.guard.as_ref())
|
||||
&& eq_expr_opt(l.body.as_deref(), r.body.as_deref())
|
||||
&& eq_expr_opt(l.guard.as_deref(), r.guard.as_deref())
|
||||
&& over(&l.attrs, &r.attrs, eq_attr)
|
||||
}
|
||||
|
||||
|
|
@ -348,7 +351,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
|||
safety: rs,
|
||||
define_opaque: _,
|
||||
}),
|
||||
) => eq_id(*li, *ri) && lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()),
|
||||
) => eq_id(*li, *ri) && lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le.as_deref(), re.as_deref()),
|
||||
(
|
||||
Const(box ConstItem {
|
||||
defaultness: ld,
|
||||
|
|
@ -371,7 +374,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
|||
&& eq_id(*li, *ri)
|
||||
&& eq_generics(lg, rg)
|
||||
&& eq_ty(lt, rt)
|
||||
&& eq_expr_opt(le.as_ref(), re.as_ref())
|
||||
&& eq_expr_opt(le.as_deref(), re.as_deref())
|
||||
},
|
||||
(
|
||||
Fn(box ast::Fn {
|
||||
|
|
@ -404,7 +407,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
|||
ls == rs
|
||||
&& eq_id(*li, *ri)
|
||||
&& match (lmk, rmk) {
|
||||
(ModKind::Loaded(litems, linline, _, _), ModKind::Loaded(ritems, rinline, _, _)) => {
|
||||
(ModKind::Loaded(litems, linline, _), ModKind::Loaded(ritems, rinline, _)) => {
|
||||
linline == rinline && over(litems, ritems, |l, r| eq_item(l, r, eq_item_kind))
|
||||
},
|
||||
(ModKind::Unloaded, ModKind::Unloaded) => true,
|
||||
|
|
@ -474,33 +477,27 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
|||
eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound)
|
||||
},
|
||||
(
|
||||
Impl(box ast::Impl {
|
||||
safety: lu,
|
||||
polarity: lp,
|
||||
defaultness: ld,
|
||||
constness: lc,
|
||||
Impl(ast::Impl {
|
||||
generics: lg,
|
||||
of_trait: lot,
|
||||
self_ty: lst,
|
||||
items: li,
|
||||
}),
|
||||
Impl(box ast::Impl {
|
||||
safety: ru,
|
||||
polarity: rp,
|
||||
defaultness: rd,
|
||||
constness: rc,
|
||||
Impl(ast::Impl {
|
||||
generics: rg,
|
||||
of_trait: rot,
|
||||
self_ty: rst,
|
||||
items: ri,
|
||||
}),
|
||||
) => {
|
||||
matches!(lu, Safety::Default) == matches!(ru, Safety::Default)
|
||||
&& matches!(lp, ImplPolarity::Positive) == matches!(rp, ImplPolarity::Positive)
|
||||
&& eq_defaultness(*ld, *rd)
|
||||
&& matches!(lc, ast::Const::No) == matches!(rc, ast::Const::No)
|
||||
&& eq_generics(lg, rg)
|
||||
&& both(lot.as_ref(), rot.as_ref(), |l, r| eq_path(&l.path, &r.path))
|
||||
eq_generics(lg, rg)
|
||||
&& both(lot.as_deref(), rot.as_deref(), |l, r| {
|
||||
matches!(l.safety, Safety::Default) == matches!(r.safety, Safety::Default)
|
||||
&& matches!(l.polarity, ImplPolarity::Positive) == matches!(r.polarity, ImplPolarity::Positive)
|
||||
&& eq_defaultness(l.defaultness, r.defaultness)
|
||||
&& matches!(l.constness, ast::Const::No) == matches!(r.constness, ast::Const::No)
|
||||
&& eq_path(&l.trait_ref.path, &r.trait_ref.path)
|
||||
})
|
||||
&& eq_ty(lst, rst)
|
||||
&& over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind))
|
||||
},
|
||||
|
|
@ -532,7 +529,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
|
|||
safety: rs,
|
||||
define_opaque: _,
|
||||
}),
|
||||
) => eq_id(*li, *ri) && eq_ty(lt, rt) && lm == rm && eq_expr_opt(le.as_ref(), re.as_ref()) && ls == rs,
|
||||
) => eq_id(*li, *ri) && eq_ty(lt, rt) && lm == rm && eq_expr_opt(le.as_deref(), re.as_deref()) && ls == rs,
|
||||
(
|
||||
Fn(box ast::Fn {
|
||||
defaultness: ld,
|
||||
|
|
@ -614,7 +611,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
|
|||
&& eq_id(*li, *ri)
|
||||
&& eq_generics(lg, rg)
|
||||
&& eq_ty(lt, rt)
|
||||
&& eq_expr_opt(le.as_ref(), re.as_ref())
|
||||
&& eq_expr_opt(le.as_deref(), re.as_deref())
|
||||
},
|
||||
(
|
||||
Fn(box ast::Fn {
|
||||
|
|
@ -727,10 +724,11 @@ pub fn eq_fn_header(l: &FnHeader, r: &FnHeader) -> bool {
|
|||
}
|
||||
|
||||
#[expect(clippy::ref_option, reason = "This is the type how it is stored in the AST")]
|
||||
pub fn eq_opt_fn_contract(l: &Option<P<FnContract>>, r: &Option<P<FnContract>>) -> bool {
|
||||
pub fn eq_opt_fn_contract(l: &Option<Box<FnContract>>, r: &Option<Box<FnContract>>) -> bool {
|
||||
match (l, r) {
|
||||
(Some(l), Some(r)) => {
|
||||
eq_expr_opt(l.requires.as_ref(), r.requires.as_ref()) && eq_expr_opt(l.ensures.as_ref(), r.ensures.as_ref())
|
||||
eq_expr_opt(l.requires.as_deref(), r.requires.as_deref())
|
||||
&& eq_expr_opt(l.ensures.as_deref(), r.ensures.as_deref())
|
||||
},
|
||||
(None, None) => true,
|
||||
(Some(_), None) | (None, Some(_)) => false,
|
||||
|
|
@ -848,7 +846,7 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool {
|
|||
&& eq_fn_decl(&l.decl, &r.decl)
|
||||
},
|
||||
(Tup(l), Tup(r)) => over(l, r, |l, r| eq_ty(l, r)),
|
||||
(Path(lq, lp), Path(rq, rp)) => both(lq.as_ref(), rq.as_ref(), eq_qself) && eq_path(lp, rp),
|
||||
(Path(lq, lp), Path(rq, rp)) => both(lq.as_deref(), rq.as_deref(), eq_qself) && eq_path(lp, rp),
|
||||
(TraitObject(lg, ls), TraitObject(rg, rs)) => ls == rs && over(lg, rg, eq_generic_bound),
|
||||
(ImplTrait(_, lg), ImplTrait(_, rg)) => over(lg, rg, eq_generic_bound),
|
||||
(Typeof(l), Typeof(r)) => eq_expr(&l.value, &r.value),
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ use rustc_hir::intravisit::FnKind;
|
|||
use rustc_hir::{
|
||||
Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, FnRetTy, HirId, Impl,
|
||||
ImplItem, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource, MatchSource, MutTy, Node, Path, QPath, Safety,
|
||||
TraitItem, TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource,
|
||||
TraitImplHeader, TraitItem, TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource,
|
||||
};
|
||||
use rustc_lint::{EarlyContext, LateContext, LintContext};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
|
@ -254,7 +254,10 @@ fn item_search_pat(item: &Item<'_>) -> (Pat, Pat) {
|
|||
ItemKind::Union(..) => (Pat::Str("union"), Pat::Str("}")),
|
||||
ItemKind::Trait(_, _, Safety::Unsafe, ..)
|
||||
| ItemKind::Impl(Impl {
|
||||
safety: Safety::Unsafe, ..
|
||||
of_trait: Some(TraitImplHeader {
|
||||
safety: Safety::Unsafe, ..
|
||||
}),
|
||||
..
|
||||
}) => (Pat::Str("unsafe"), Pat::Str("}")),
|
||||
ItemKind::Trait(_, IsAuto::Yes, ..) => (Pat::Str("auto"), Pat::Str("}")),
|
||||
ItemKind::Trait(..) => (Pat::Str("trait"), Pat::Str("}")),
|
||||
|
|
|
|||
|
|
@ -545,8 +545,9 @@ pub fn path_def_id<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>
|
|||
pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, owner: OwnerId) -> Option<&'tcx TraitRef<'tcx>> {
|
||||
if let Node::Item(item) = cx.tcx.hir_node(cx.tcx.hir_owner_parent(owner))
|
||||
&& let ItemKind::Impl(impl_) = &item.kind
|
||||
&& let Some(of_trait) = impl_.of_trait
|
||||
{
|
||||
return impl_.of_trait.as_ref();
|
||||
return Some(&of_trait.trait_ref);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,18 +250,13 @@ impl<'a> PanicExpn<'a> {
|
|||
};
|
||||
let name = path.segments.last().unwrap().ident.name;
|
||||
|
||||
// This has no argument
|
||||
if name == sym::panic_cold_explicit {
|
||||
return Some(Self::Empty);
|
||||
}
|
||||
|
||||
let [arg, rest @ ..] = args else {
|
||||
return None;
|
||||
};
|
||||
let result = match name {
|
||||
sym::panic if arg.span.eq_ctxt(expr.span) => Self::Empty,
|
||||
sym::panic | sym::panic_str => Self::Str(arg),
|
||||
sym::panic_display | sym::panic_cold_display => {
|
||||
sym::panic_display => {
|
||||
let ExprKind::AddrOf(_, _, e) = &arg.kind else {
|
||||
return None;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -241,9 +241,6 @@ generate! {
|
|||
or_insert,
|
||||
or_insert_with,
|
||||
outer_expn,
|
||||
panic_cold_display,
|
||||
panic_cold_explicit,
|
||||
panic_display,
|
||||
panic_str,
|
||||
parse,
|
||||
partition,
|
||||
|
|
|
|||
|
|
@ -460,7 +460,8 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool {
|
|||
}
|
||||
fn visit_nested_item(&mut self, id: ItemId) -> Self::Result {
|
||||
if let ItemKind::Impl(i) = &self.cx.tcx.hir_item(id).kind
|
||||
&& i.safety.is_unsafe()
|
||||
&& let Some(of_trait) = i.of_trait
|
||||
&& of_trait.safety.is_unsafe()
|
||||
{
|
||||
ControlFlow::Break(())
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[toolchain]
|
||||
# begin autogenerated nightly
|
||||
channel = "nightly-2025-08-07"
|
||||
channel = "nightly-2025-08-22"
|
||||
# end autogenerated nightly
|
||||
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
||||
profile = "minimal"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||
#![allow(clippy::assertions_on_constants)]
|
||||
#![feature(path_file_prefix)]
|
||||
#![cfg_attr(bootstrap, feature(path_file_prefix))]
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::ffi::OsStr;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#![allow(unused, clippy::assertions_on_constants, clippy::const_is_empty)]
|
||||
#![warn(clippy::bool_assert_comparison)]
|
||||
|
||||
use std::ops::Not;
|
||||
use std::ops::{Add, Not};
|
||||
|
||||
macro_rules! a {
|
||||
() => {
|
||||
|
|
@ -62,6 +62,14 @@ impl Not for ImplNotTraitWithBool {
|
|||
}
|
||||
}
|
||||
|
||||
impl Add for ImplNotTraitWithBool {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: Self) -> Self::Output {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct NonCopy;
|
||||
|
||||
|
|
@ -94,7 +102,7 @@ fn main() {
|
|||
assert_eq!(a!(), "".is_empty());
|
||||
assert_eq!("".is_empty(), b!());
|
||||
assert_eq!(a, true);
|
||||
assert!(b);
|
||||
assert!(!!b);
|
||||
//~^ bool_assert_comparison
|
||||
|
||||
assert_ne!("a".len(), 1);
|
||||
|
|
@ -122,7 +130,7 @@ fn main() {
|
|||
debug_assert_eq!(a!(), "".is_empty());
|
||||
debug_assert_eq!("".is_empty(), b!());
|
||||
debug_assert_eq!(a, true);
|
||||
debug_assert!(b);
|
||||
debug_assert!(!!b);
|
||||
//~^ bool_assert_comparison
|
||||
|
||||
debug_assert_ne!("a".len(), 1);
|
||||
|
|
@ -167,7 +175,7 @@ fn main() {
|
|||
|
||||
use debug_assert_eq as renamed;
|
||||
renamed!(a, true);
|
||||
debug_assert!(b);
|
||||
debug_assert!(!!b);
|
||||
//~^ bool_assert_comparison
|
||||
|
||||
let non_copy = NonCopy;
|
||||
|
|
@ -199,4 +207,12 @@ fn main() {
|
|||
//~^ bool_assert_comparison
|
||||
debug_assert!(!"requires negation".is_empty());
|
||||
//~^ bool_assert_comparison
|
||||
assert!(!b);
|
||||
//~^ bool_assert_comparison
|
||||
assert!(!(!b));
|
||||
//~^ bool_assert_comparison
|
||||
assert!(!!(b + b));
|
||||
//~^ bool_assert_comparison
|
||||
assert!(!(b + b));
|
||||
//~^ bool_assert_comparison
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#![allow(unused, clippy::assertions_on_constants, clippy::const_is_empty)]
|
||||
#![warn(clippy::bool_assert_comparison)]
|
||||
|
||||
use std::ops::Not;
|
||||
use std::ops::{Add, Not};
|
||||
|
||||
macro_rules! a {
|
||||
() => {
|
||||
|
|
@ -62,6 +62,14 @@ impl Not for ImplNotTraitWithBool {
|
|||
}
|
||||
}
|
||||
|
||||
impl Add for ImplNotTraitWithBool {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: Self) -> Self::Output {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct NonCopy;
|
||||
|
||||
|
|
@ -199,4 +207,12 @@ fn main() {
|
|||
//~^ bool_assert_comparison
|
||||
debug_assert_eq!("requires negation".is_empty(), false);
|
||||
//~^ bool_assert_comparison
|
||||
assert_eq!(!b, true);
|
||||
//~^ bool_assert_comparison
|
||||
assert_eq!(!b, false);
|
||||
//~^ bool_assert_comparison
|
||||
assert_eq!(b + b, true);
|
||||
//~^ bool_assert_comparison
|
||||
assert_eq!(b + b, false);
|
||||
//~^ bool_assert_comparison
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: used `assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:87:5
|
||||
--> tests/ui/bool_assert_comparison.rs:95:5
|
||||
|
|
||||
LL | assert_eq!("a".is_empty(), false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -13,7 +13,7 @@ LL + assert!(!"a".is_empty());
|
|||
|
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:89:5
|
||||
--> tests/ui/bool_assert_comparison.rs:97:5
|
||||
|
|
||||
LL | assert_eq!("".is_empty(), true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -25,7 +25,7 @@ LL + assert!("".is_empty());
|
|||
|
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:91:5
|
||||
--> tests/ui/bool_assert_comparison.rs:99:5
|
||||
|
|
||||
LL | assert_eq!(true, "".is_empty());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -37,7 +37,7 @@ LL + assert!("".is_empty());
|
|||
|
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:97:5
|
||||
--> tests/ui/bool_assert_comparison.rs:105:5
|
||||
|
|
||||
LL | assert_eq!(b, true);
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -45,11 +45,11 @@ LL | assert_eq!(b, true);
|
|||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_eq!(b, true);
|
||||
LL + assert!(b);
|
||||
LL + assert!(!!b);
|
||||
|
|
||||
|
||||
error: used `assert_ne!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:101:5
|
||||
--> tests/ui/bool_assert_comparison.rs:109:5
|
||||
|
|
||||
LL | assert_ne!("a".is_empty(), false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -61,7 +61,7 @@ LL + assert!("a".is_empty());
|
|||
|
|
||||
|
||||
error: used `assert_ne!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:103:5
|
||||
--> tests/ui/bool_assert_comparison.rs:111:5
|
||||
|
|
||||
LL | assert_ne!("".is_empty(), true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -73,7 +73,7 @@ LL + assert!(!"".is_empty());
|
|||
|
|
||||
|
||||
error: used `assert_ne!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:105:5
|
||||
--> tests/ui/bool_assert_comparison.rs:113:5
|
||||
|
|
||||
LL | assert_ne!(true, "".is_empty());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -85,7 +85,7 @@ LL + assert!(!"".is_empty());
|
|||
|
|
||||
|
||||
error: used `assert_ne!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:111:5
|
||||
--> tests/ui/bool_assert_comparison.rs:119:5
|
||||
|
|
||||
LL | assert_ne!(b, true);
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -97,7 +97,7 @@ LL + assert!(!b);
|
|||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:115:5
|
||||
--> tests/ui/bool_assert_comparison.rs:123:5
|
||||
|
|
||||
LL | debug_assert_eq!("a".is_empty(), false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -109,7 +109,7 @@ LL + debug_assert!(!"a".is_empty());
|
|||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:117:5
|
||||
--> tests/ui/bool_assert_comparison.rs:125:5
|
||||
|
|
||||
LL | debug_assert_eq!("".is_empty(), true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -121,7 +121,7 @@ LL + debug_assert!("".is_empty());
|
|||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:119:5
|
||||
--> tests/ui/bool_assert_comparison.rs:127:5
|
||||
|
|
||||
LL | debug_assert_eq!(true, "".is_empty());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -133,7 +133,7 @@ LL + debug_assert!("".is_empty());
|
|||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:125:5
|
||||
--> tests/ui/bool_assert_comparison.rs:133:5
|
||||
|
|
||||
LL | debug_assert_eq!(b, true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -141,11 +141,11 @@ LL | debug_assert_eq!(b, true);
|
|||
help: replace it with `debug_assert!(..)`
|
||||
|
|
||||
LL - debug_assert_eq!(b, true);
|
||||
LL + debug_assert!(b);
|
||||
LL + debug_assert!(!!b);
|
||||
|
|
||||
|
||||
error: used `debug_assert_ne!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:129:5
|
||||
--> tests/ui/bool_assert_comparison.rs:137:5
|
||||
|
|
||||
LL | debug_assert_ne!("a".is_empty(), false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -157,7 +157,7 @@ LL + debug_assert!("a".is_empty());
|
|||
|
|
||||
|
||||
error: used `debug_assert_ne!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:131:5
|
||||
--> tests/ui/bool_assert_comparison.rs:139:5
|
||||
|
|
||||
LL | debug_assert_ne!("".is_empty(), true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -169,7 +169,7 @@ LL + debug_assert!(!"".is_empty());
|
|||
|
|
||||
|
||||
error: used `debug_assert_ne!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:133:5
|
||||
--> tests/ui/bool_assert_comparison.rs:141:5
|
||||
|
|
||||
LL | debug_assert_ne!(true, "".is_empty());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -181,7 +181,7 @@ LL + debug_assert!(!"".is_empty());
|
|||
|
|
||||
|
||||
error: used `debug_assert_ne!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:139:5
|
||||
--> tests/ui/bool_assert_comparison.rs:147:5
|
||||
|
|
||||
LL | debug_assert_ne!(b, true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -193,7 +193,7 @@ LL + debug_assert!(!b);
|
|||
|
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:145:5
|
||||
--> tests/ui/bool_assert_comparison.rs:153:5
|
||||
|
|
||||
LL | assert_eq!("a".is_empty(), false, "tadam {}", 1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -205,7 +205,7 @@ LL + assert!(!"a".is_empty(), "tadam {}", 1);
|
|||
|
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:147:5
|
||||
--> tests/ui/bool_assert_comparison.rs:155:5
|
||||
|
|
||||
LL | assert_eq!("a".is_empty(), false, "tadam {}", true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -217,7 +217,7 @@ LL + assert!(!"a".is_empty(), "tadam {}", true);
|
|||
|
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:149:5
|
||||
--> tests/ui/bool_assert_comparison.rs:157:5
|
||||
|
|
||||
LL | assert_eq!(false, "a".is_empty(), "tadam {}", true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -229,7 +229,7 @@ LL + assert!(!"a".is_empty(), "tadam {}", true);
|
|||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:155:5
|
||||
--> tests/ui/bool_assert_comparison.rs:163:5
|
||||
|
|
||||
LL | debug_assert_eq!("a".is_empty(), false, "tadam {}", 1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -241,7 +241,7 @@ LL + debug_assert!(!"a".is_empty(), "tadam {}", 1);
|
|||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:157:5
|
||||
--> tests/ui/bool_assert_comparison.rs:165:5
|
||||
|
|
||||
LL | debug_assert_eq!("a".is_empty(), false, "tadam {}", true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -253,7 +253,7 @@ LL + debug_assert!(!"a".is_empty(), "tadam {}", true);
|
|||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:159:5
|
||||
--> tests/ui/bool_assert_comparison.rs:167:5
|
||||
|
|
||||
LL | debug_assert_eq!(false, "a".is_empty(), "tadam {}", true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -265,31 +265,35 @@ LL + debug_assert!(!"a".is_empty(), "tadam {}", true);
|
|||
|
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:163:5
|
||||
--> tests/ui/bool_assert_comparison.rs:171:5
|
||||
|
|
||||
LL | assert_eq!(a!(), true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_eq!(a!(), true);
|
||||
LL + assert!(a!());
|
||||
LL | true
|
||||
...
|
||||
LL |
|
||||
LL ~ assert!(a!());
|
||||
|
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:165:5
|
||||
--> tests/ui/bool_assert_comparison.rs:173:5
|
||||
|
|
||||
LL | assert_eq!(true, b!());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_eq!(true, b!());
|
||||
LL + assert!(b!());
|
||||
LL | true
|
||||
...
|
||||
LL |
|
||||
LL ~ assert!(b!());
|
||||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:170:5
|
||||
--> tests/ui/bool_assert_comparison.rs:178:5
|
||||
|
|
||||
LL | renamed!(b, true);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -297,11 +301,11 @@ LL | renamed!(b, true);
|
|||
help: replace it with `debug_assert!(..)`
|
||||
|
|
||||
LL - renamed!(b, true);
|
||||
LL + debug_assert!(b);
|
||||
LL + debug_assert!(!!b);
|
||||
|
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:185:5
|
||||
--> tests/ui/bool_assert_comparison.rs:193:5
|
||||
|
|
||||
LL | assert_eq!("".is_empty(), true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -313,7 +317,7 @@ LL + assert!("".is_empty());
|
|||
|
|
||||
|
||||
error: used `assert_ne!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:187:5
|
||||
--> tests/ui/bool_assert_comparison.rs:195:5
|
||||
|
|
||||
LL | assert_ne!("".is_empty(), false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -325,7 +329,7 @@ LL + assert!("".is_empty());
|
|||
|
|
||||
|
||||
error: used `assert_ne!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:189:5
|
||||
--> tests/ui/bool_assert_comparison.rs:197:5
|
||||
|
|
||||
LL | assert_ne!("requires negation".is_empty(), true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -337,7 +341,7 @@ LL + assert!(!"requires negation".is_empty());
|
|||
|
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:191:5
|
||||
--> tests/ui/bool_assert_comparison.rs:199:5
|
||||
|
|
||||
LL | assert_eq!("requires negation".is_empty(), false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -349,7 +353,7 @@ LL + assert!(!"requires negation".is_empty());
|
|||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:194:5
|
||||
--> tests/ui/bool_assert_comparison.rs:202:5
|
||||
|
|
||||
LL | debug_assert_eq!("".is_empty(), true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -361,7 +365,7 @@ LL + debug_assert!("".is_empty());
|
|||
|
|
||||
|
||||
error: used `debug_assert_ne!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:196:5
|
||||
--> tests/ui/bool_assert_comparison.rs:204:5
|
||||
|
|
||||
LL | debug_assert_ne!("".is_empty(), false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -373,7 +377,7 @@ LL + debug_assert!("".is_empty());
|
|||
|
|
||||
|
||||
error: used `debug_assert_ne!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:198:5
|
||||
--> tests/ui/bool_assert_comparison.rs:206:5
|
||||
|
|
||||
LL | debug_assert_ne!("requires negation".is_empty(), true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -385,7 +389,7 @@ LL + debug_assert!(!"requires negation".is_empty());
|
|||
|
|
||||
|
||||
error: used `debug_assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:200:5
|
||||
--> tests/ui/bool_assert_comparison.rs:208:5
|
||||
|
|
||||
LL | debug_assert_eq!("requires negation".is_empty(), false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -396,5 +400,53 @@ LL - debug_assert_eq!("requires negation".is_empty(), false);
|
|||
LL + debug_assert!(!"requires negation".is_empty());
|
||||
|
|
||||
|
||||
error: aborting due to 33 previous errors
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:210:5
|
||||
|
|
||||
LL | assert_eq!(!b, true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_eq!(!b, true);
|
||||
LL + assert!(!b);
|
||||
|
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:212:5
|
||||
|
|
||||
LL | assert_eq!(!b, false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_eq!(!b, false);
|
||||
LL + assert!(!(!b));
|
||||
|
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:214:5
|
||||
|
|
||||
LL | assert_eq!(b + b, true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_eq!(b + b, true);
|
||||
LL + assert!(!!(b + b));
|
||||
|
|
||||
|
||||
error: used `assert_eq!` with a literal bool
|
||||
--> tests/ui/bool_assert_comparison.rs:216:5
|
||||
|
|
||||
LL | assert_eq!(b + b, false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace it with `assert!(..)`
|
||||
|
|
||||
LL - assert_eq!(b + b, false);
|
||||
LL + assert!(!(b + b));
|
||||
|
|
||||
|
||||
error: aborting due to 37 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ LL | if X.is_some() {
|
|||
|
|
||||
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
|
||||
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
|
||||
= note: `#[deny(static_mut_refs)]` on by default
|
||||
= note: `#[deny(static_mut_refs)]` (part of `#[deny(rust_2024_compatibility)]`) on by default
|
||||
|
||||
error: aborting due to 36 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -196,6 +196,7 @@ fn issue_13106() {
|
|||
|
||||
const {
|
||||
assert!(EMPTY_STR.is_empty());
|
||||
//~^ const_is_empty
|
||||
}
|
||||
|
||||
const {
|
||||
|
|
|
|||
|
|
@ -158,10 +158,16 @@ LL | let _ = val.is_empty();
|
|||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: this expression always evaluates to true
|
||||
--> tests/ui/const_is_empty.rs:202:9
|
||||
--> tests/ui/const_is_empty.rs:198:17
|
||||
|
|
||||
LL | assert!(EMPTY_STR.is_empty());
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: this expression always evaluates to true
|
||||
--> tests/ui/const_is_empty.rs:203:9
|
||||
|
|
||||
LL | EMPTY_STR.is_empty();
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 27 previous errors
|
||||
error: aborting due to 28 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ macro_rules! define_other_core {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
core::panic!();
|
||||
core::panic!(); //~ ERROR: `core` is ambiguous
|
||||
}
|
||||
|
||||
define_other_core!();
|
||||
|
|
|
|||
|
|
@ -9,5 +9,25 @@ LL | define_other_core!();
|
|||
|
|
||||
= note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error[E0659]: `core` is ambiguous
|
||||
--> tests/ui/crashes/ice-6255.rs:12:5
|
||||
|
|
||||
LL | core::panic!();
|
||||
| ^^^^ ambiguous name
|
||||
|
|
||||
= note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
|
||||
= note: `core` could refer to a built-in crate
|
||||
note: `core` could also refer to the crate imported here
|
||||
--> tests/ui/crashes/ice-6255.rs:6:9
|
||||
|
|
||||
LL | extern crate std as core;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | define_other_core!();
|
||||
| -------------------- in this macro invocation
|
||||
= help: use `crate::core` to refer to this crate unambiguously
|
||||
= note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0659`.
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ error: malformed `path` attribute input
|
|||
|
|
||||
LL | #[path = foo!()]
|
||||
| ^^^^^^^^^^^^^^^^ help: must be of the form: `#[path = "file"]`
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/items/modules.html#the-path-attribute>
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#![warn(clippy::incompatible_msrv)]
|
||||
#![feature(custom_inner_attributes)]
|
||||
#![allow(stable_features)]
|
||||
#![allow(stable_features, clippy::diverging_sub_expression)]
|
||||
#![feature(strict_provenance)] // For use in test
|
||||
#![clippy::msrv = "1.3.0"]
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue