about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-06-22 17:10:28 +0000
committerbors <bors@rust-lang.org>2025-06-22 17:10:28 +0000
commit111e9bc64bbdce14122e3676978f2ceefa5bff1a (patch)
tree28ed5aecce63ba1a3279eaa86a818cf899cd4dba /src
parentc2ec7532eed172e79800d28f087727c4b048badd (diff)
parent8da1a6290d0a097a497e109e70651c4f55e0fadb (diff)
Auto merge of #142878 - GuillaumeGomez:rollup-53dohob, r=GuillaumeGomez
Rollup of 10 pull requests

Successful merges:

 - rust-lang/rust#142458 (Merge unboxed trait object error suggestion into regular dyn incompat error)
 - rust-lang/rust#142593 (Add a warning to LateContext::get_def_path)
 - rust-lang/rust#142594 (Add DesugaringKind::FormatLiteral)
 - rust-lang/rust#142740 (Clean-up `FnCtxt::is_destruct_assignment_desugaring`)
 - rust-lang/rust#142780 (Port `#[must_use]` to new attribute parsing infrastructure)
 - rust-lang/rust#142798 (Don't fail to parse a struct if a semicolon is used to separate fields)
 - rust-lang/rust#142856 (Add a few inline directives in rustc_serialize.)
 - rust-lang/rust#142868 (remove few allow(dead_code))
 - rust-lang/rust#142874 (cranelift: fix target feature name typo: "fxsr")
 - rust-lang/rust#142877 (Document why tidy checks if `eslint` is installed via `npm`)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/src/core/build_steps/setup.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs1
-rw-r--r--src/rustdoc-json-types/lib.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/must_use.rs30
-rw-r--r--src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs9
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs5
-rw-r--r--src/tools/clippy/clippy_utils/src/ty/mod.rs16
-rw-r--r--src/tools/tidy/src/rustdoc_js.rs3
8 files changed, 46 insertions, 24 deletions
diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs
index 86b7456d7b4..9ce81ff9a22 100644
--- a/src/bootstrap/src/core/build_steps/setup.rs
+++ b/src/bootstrap/src/core/build_steps/setup.rs
@@ -531,7 +531,7 @@ enum EditorKind {
 
 impl EditorKind {
     // Used in `./tests.rs`.
-    #[allow(dead_code)]
+    #[cfg(test)]
     pub const ALL: &[EditorKind] = &[
         EditorKind::Emacs,
         EditorKind::Helix,
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 1594080815f..248ee4196b8 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -390,7 +390,6 @@ macro_rules! bootstrap_tool {
         ;
     )+) => {
         #[derive(PartialEq, Eq, Clone)]
-        #[allow(dead_code)]
         pub enum Tool {
             $(
                 $name,
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index c9b4da183a3..e5c246cb69c 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -37,8 +37,8 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc
 // will instead cause conflicts. See #94591 for more. (This paragraph and the "Latest feature" line
 // are deliberately not in a doc comment, because they need not be in public docs.)
 //
-// Latest feature: improve handling of generic args
-pub const FORMAT_VERSION: u32 = 51;
+// Latest feature: Pretty printing of must_use attributes changed
+pub const FORMAT_VERSION: u32 = 52;
 
 /// The root of the emitted JSON blob.
 ///
diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
index 70655838b6a..ea9ed4ddade 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -15,6 +15,9 @@ use clippy_utils::ty::is_must_use_ty;
 use clippy_utils::visitors::for_each_expr_without_closures;
 use clippy_utils::{return_ty, trait_ref_of_method};
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
+use rustc_attr_data_structures::AttributeKind;
+use rustc_span::Symbol;
+use rustc_attr_data_structures::find_attr;
 
 use core::ops::ControlFlow;
 
@@ -22,7 +25,7 @@ use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT};
 
 pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
     let attrs = cx.tcx.hir_attrs(item.hir_id());
-    let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
+    let attr = find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::MustUse { span, reason } => (span, reason));
     if let hir::ItemKind::Fn {
         ref sig,
         body: ref body_id,
@@ -31,8 +34,8 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>
     {
         let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
-        if let Some(attr) = attr {
-            check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig);
+        if let Some((attr_span, reason)) = attr {
+            check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, *attr_span, *reason, attrs, sig);
         } else if is_public && !is_proc_macro(attrs) && !attrs.iter().any(|a| a.has_name(sym::no_mangle)) {
             check_must_use_candidate(
                 cx,
@@ -52,9 +55,9 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
         let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
         let attrs = cx.tcx.hir_attrs(item.hir_id());
-        let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
-        if let Some(attr) = attr {
-            check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig);
+        let attr = find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::MustUse { span, reason } => (span, reason));
+        if let Some((attr_span, reason)) = attr {
+            check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, *attr_span, *reason, attrs, sig);
         } else if is_public && !is_proc_macro(attrs) && trait_ref_of_method(cx, item.owner_id).is_none() {
             check_must_use_candidate(
                 cx,
@@ -75,9 +78,9 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
 
         let attrs = cx.tcx.hir_attrs(item.hir_id());
-        let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
-        if let Some(attr) = attr {
-            check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig);
+        let attr = find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::MustUse { span, reason } => (span, reason));
+        if let Some((attr_span, reason)) = attr {
+            check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, *attr_span, *reason, attrs, sig);
         } else if let hir::TraitFn::Provided(eid) = *eid {
             let body = cx.tcx.hir_body(eid);
             if attr.is_none() && is_public && !is_proc_macro(attrs) {
@@ -103,7 +106,8 @@ fn check_needless_must_use(
     item_id: hir::OwnerId,
     item_span: Span,
     fn_header_span: Span,
-    attr: &Attribute,
+    attr_span: Span,
+    reason: Option<Symbol>,
     attrs: &[Attribute],
     sig: &FnSig<'_>,
 ) {
@@ -119,7 +123,7 @@ fn check_needless_must_use(
                 "this unit-returning function has a `#[must_use]` attribute",
                 |diag| {
                     diag.span_suggestion(
-                        attr.span(),
+                        attr_span,
                         "remove the attribute",
                         "",
                         Applicability::MachineApplicable,
@@ -137,11 +141,11 @@ fn check_needless_must_use(
                 MUST_USE_UNIT,
                 fn_header_span,
                 "this unit-returning function has a `#[must_use]` attribute",
-                Some(attr.span()),
+                Some(attr_span),
                 "remove `must_use`",
             );
         }
-    } else if attr.value_str().is_none() && is_must_use_ty(cx, return_ty(cx, item_id)) {
+    } else if reason.is_none() && is_must_use_ty(cx, return_ty(cx, item_id)) {
         // Ignore async functions unless Future::Output type is a must_use type
         if sig.header.is_async() {
             let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
diff --git a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
index 07ae92fa984..1b304dc5768 100644
--- a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
@@ -6,7 +6,9 @@ use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, FnDecl, OwnerId, TraitItem, TraitItemKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::declare_lint_pass;
-use rustc_span::{Span, sym};
+use rustc_span::{Span};
+use rustc_attr_data_structures::AttributeKind;
+use rustc_attr_data_structures::find_attr;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -74,7 +76,10 @@ fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, spa
         // We only show this warning for public exported methods.
         && cx.effective_visibilities.is_exported(fn_def)
         // We don't want to emit this lint if the `#[must_use]` attribute is already there.
-        && !cx.tcx.hir_attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use))
+        && !find_attr!(
+            cx.tcx.hir_attrs(owner_id.into()),
+            AttributeKind::MustUse { .. }
+        )
         && cx.tcx.visibility(fn_def.to_def_id()).is_public()
         && let ret_ty = return_ty(cx, owner_id)
         && let self_arg = nth_arg(cx, owner_id, 0)
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index c7a2375c8df..913589319fc 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1886,7 +1886,10 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
         _ => None,
     };
 
-    did.is_some_and(|did| cx.tcx.has_attr(did, sym::must_use))
+    did.is_some_and(|did| find_attr!(
+            cx.tcx.get_all_attrs(did),
+            AttributeKind::MustUse { ..}
+        ))
 }
 
 /// Checks if a function's body represents the identity function. Looks for bodies of the form:
diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs
index 32a992ccc2d..782b079ce09 100644
--- a/src/tools/clippy/clippy_utils/src/ty/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs
@@ -31,6 +31,8 @@ use rustc_trait_selection::traits::{Obligation, ObligationCause};
 use std::assert_matches::debug_assert_matches;
 use std::collections::hash_map::Entry;
 use std::iter;
+use rustc_attr_data_structures::find_attr;
+use rustc_attr_data_structures::AttributeKind;
 
 use crate::path_res;
 use crate::paths::{PathNS, lookup_path_str};
@@ -326,8 +328,14 @@ pub fn has_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
 // Returns whether the type has #[must_use] attribute
 pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
     match ty.kind() {
-        ty::Adt(adt, _) => cx.tcx.has_attr(adt.did(), sym::must_use),
-        ty::Foreign(did) => cx.tcx.has_attr(*did, sym::must_use),
+        ty::Adt(adt, _) => find_attr!(
+            cx.tcx.get_all_attrs(adt.did()),
+            AttributeKind::MustUse { ..}
+        ),
+        ty::Foreign(did) => find_attr!(
+            cx.tcx.get_all_attrs(*did),
+            AttributeKind::MustUse { ..}
+        ),
         ty::Slice(ty) | ty::Array(ty, _) | ty::RawPtr(ty, _) | ty::Ref(_, ty, _) => {
             // for the Array case we don't need to care for the len == 0 case
             // because we don't want to lint functions returning empty arrays
@@ -337,7 +345,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
         ty::Alias(ty::Opaque, AliasTy { def_id, .. }) => {
             for (predicate, _) in cx.tcx.explicit_item_self_bounds(def_id).skip_binder() {
                 if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder()
-                    && cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use)
+                    && find_attr!(cx.tcx.get_all_attrs(trait_predicate.trait_ref.def_id), AttributeKind::MustUse { ..})
                 {
                     return true;
                 }
@@ -347,7 +355,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
         ty::Dynamic(binder, _, _) => {
             for predicate in *binder {
                 if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder()
-                    && cx.tcx.has_attr(trait_ref.def_id, sym::must_use)
+                    && find_attr!(cx.tcx.get_all_attrs(trait_ref.def_id), AttributeKind::MustUse { ..})
                 {
                     return true;
                 }
diff --git a/src/tools/tidy/src/rustdoc_js.rs b/src/tools/tidy/src/rustdoc_js.rs
index 2517e2de12c..720f0712ee0 100644
--- a/src/tools/tidy/src/rustdoc_js.rs
+++ b/src/tools/tidy/src/rustdoc_js.rs
@@ -62,6 +62,9 @@ pub fn check(librustdoc_path: &Path, tools_path: &Path, src_path: &Path, bad: &m
             return;
         }
     };
+    // Having the correct `eslint` version installed via `npm` isn't strictly necessary, since we're invoking it via `npx`,
+    // but this check allows the vast majority that is not working on the rustdoc frontend to avoid the penalty of running
+    // `eslint` in tidy. See also: https://github.com/rust-lang/rust/pull/142851
     match get_eslint_version() {
         Some(version) => {
             if version != eslint_version {