about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPhilipp Krones <hello@philkrones.com>2022-11-05 15:08:37 +0100
committerPhilipp Krones <hello@philkrones.com>2022-11-17 20:06:25 +0100
commit4e65f5ea82aa8c128c4dc8611677019679a9bc67 (patch)
tree8e4808fae244041fc619ffc680e299a0b6cd29dd
parentb6097f2e1b2ca62e188ba53cf43bd66b06b36915 (diff)
downloadrust-4e65f5ea82aa8c128c4dc8611677019679a9bc67.tar.gz
rust-4e65f5ea82aa8c128c4dc8611677019679a9bc67.zip
Add variant_name function to `LangItem`
Clippy has an internal lint that checks for the usage of hardcoded def
paths and suggests to replace them with a lang or diagnostic item, if
possible. This was implemented with a hack, by getting all the variants
of the `LangItem` enum and then index into it with the position of the
`LangItem` in the `items` list. This is no longer possible, because the
`items` list can't be accessed anymore.
-rw-r--r--compiler/rustc_hir/src/lang_items.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs19
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed6
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr6
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr20
6 files changed, 35 insertions, 36 deletions
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index a55224d1097..230d250ff88 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -95,6 +95,14 @@ macro_rules! language_item_table {
                 }
             }
 
+            /// Returns the name of the `LangItem` enum variant.
+            // This method is used by Clippy for internal lints.
+            pub fn variant_name(self) -> &'static str {
+                match self {
+                    $( LangItem::$variant => stringify!($variant), )*
+                }
+            }
+
             pub fn target(self) -> Target {
                 match self {
                     $( LangItem::$variant => $target, )*
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
index 25532dd4e26..22a5aa5351a 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
@@ -79,22 +79,22 @@ pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool {
         SimplifiedTypeGen::StrSimplifiedType,
     ]
     .iter()
-    .flat_map(|&ty| cx.tcx.incoherent_impls(ty));
-    for item_def_id in lang_items.items().iter().flatten().chain(incoherent_impls) {
-        let lang_item_path = cx.get_def_path(*item_def_id);
+    .flat_map(|&ty| cx.tcx.incoherent_impls(ty).iter().copied());
+    for item_def_id in lang_items.iter().map(|(_, def_id)| def_id).chain(incoherent_impls) {
+        let lang_item_path = cx.get_def_path(item_def_id);
         if path_syms.starts_with(&lang_item_path) {
             if let [item] = &path_syms[lang_item_path.len()..] {
                 if matches!(
-                    cx.tcx.def_kind(*item_def_id),
+                    cx.tcx.def_kind(item_def_id),
                     DefKind::Mod | DefKind::Enum | DefKind::Trait
                 ) {
-                    for child in cx.tcx.module_children(*item_def_id) {
+                    for child in cx.tcx.module_children(item_def_id) {
                         if child.ident.name == *item {
                             return true;
                         }
                     }
                 } else {
-                    for child in cx.tcx.associated_item_def_ids(*item_def_id) {
+                    for child in cx.tcx.associated_item_def_ids(item_def_id) {
                         if cx.tcx.item_name(*child) == *item {
                             return true;
                         }
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
index 2a028c8141f..cfba7fa8791 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
@@ -6,7 +6,7 @@ use rustc_ast::ast::LitKind;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Namespace, Res};
+use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, ExprKind, Local, Mutability, Node};
 use rustc_lint::{LateContext, LateLintPass};
@@ -91,7 +91,7 @@ impl UnnecessaryDefPath {
     #[allow(clippy::too_many_lines)]
     fn check_call(&mut self, cx: &LateContext<'_>, func: &Expr<'_>, args: &[Expr<'_>], span: Span) {
         enum Item {
-            LangItem(Symbol),
+            LangItem(&'static str),
             DiagnosticItem(Symbol),
         }
         static PATHS: &[&[&str]] = &[
@@ -325,18 +325,9 @@ fn inherent_def_path_res(cx: &LateContext<'_>, segments: &[&str]) -> Option<DefI
     })
 }
 
-fn get_lang_item_name(cx: &LateContext<'_>, def_id: DefId) -> Option<Symbol> {
-    if let Some(lang_item) = cx.tcx.lang_items().items().iter().position(|id| *id == Some(def_id)) {
-        let lang_items = def_path_res(cx, &["rustc_hir", "lang_items", "LangItem"], Some(Namespace::TypeNS)).def_id();
-        let item_name = cx
-            .tcx
-            .adt_def(lang_items)
-            .variants()
-            .iter()
-            .nth(lang_item)
-            .unwrap()
-            .name;
-        Some(item_name)
+fn get_lang_item_name(cx: &LateContext<'_>, def_id: DefId) -> Option<&'static str> {
+    if let Some((lang_item, _)) = cx.tcx.lang_items().iter().find(|(_, id)| *id == def_id) {
+        Some(lang_item.variant_name())
     } else {
         None
     }
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
index cbbb4652306..e474f370a5d 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
@@ -48,14 +48,14 @@ fn _f<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, did: DefId, expr: &Expr<'_>) {
     let _ = is_type_lang_item(cx, ty, LangItem::OwnedBox);
     let _ = is_type_diagnostic_item(cx, ty, sym::maybe_uninit_uninit);
 
-    let _ = cx.tcx.lang_items().require(LangItem::OwnedBox).ok() == Some(did);
+    let _ = cx.tcx.lang_items().get(LangItem::OwnedBox) == Some(did);
     let _ = cx.tcx.is_diagnostic_item(sym::Option, did);
-    let _ = cx.tcx.lang_items().require(LangItem::OptionSome).ok() == Some(did);
+    let _ = cx.tcx.lang_items().get(LangItem::OptionSome) == Some(did);
 
     let _ = is_trait_method(cx, expr, sym::AsRef);
 
     let _ = is_path_diagnostic_item(cx, expr, sym::Option);
-    let _ = path_res(cx, expr).opt_def_id().map_or(false, |id| cx.tcx.lang_items().require(LangItem::IteratorNext).ok() == Some(id));
+    let _ = path_res(cx, expr).opt_def_id().map_or(false, |id| cx.tcx.lang_items().get(LangItem::IteratorNext) == Some(id));
     let _ = is_res_lang_ctor(cx, path_res(cx, expr), LangItem::OptionSome);
 }
 
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr
index a99a8f71fa6..3ca29f09977 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr
@@ -57,7 +57,7 @@ error: use of a def path to a `LangItem`
   --> $DIR/unnecessary_def_path.rs:51:13
    |
 LL |     let _ = match_def_path(cx, did, &["alloc", "boxed", "Box"]);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().require(LangItem::OwnedBox).ok() == Some(did)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().get(LangItem::OwnedBox) == Some(did)`
 
 error: use of a def path to a diagnostic item
   --> $DIR/unnecessary_def_path.rs:52:13
@@ -69,7 +69,7 @@ error: use of a def path to a `LangItem`
   --> $DIR/unnecessary_def_path.rs:53:13
    |
 LL |     let _ = match_def_path(cx, did, &["core", "option", "Option", "Some"]);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().require(LangItem::OptionSome).ok() == Some(did)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().get(LangItem::OptionSome) == Some(did)`
    |
    = help: if this `DefId` came from a constructor expression or pattern then the parent `DefId` should be used instead
 
@@ -89,7 +89,7 @@ error: use of a def path to a `LangItem`
   --> $DIR/unnecessary_def_path.rs:58:13
    |
 LL |     let _ = is_expr_path_def_path(cx, expr, &["core", "iter", "traits", "Iterator", "next"]);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `path_res(cx, expr).opt_def_id().map_or(false, |id| cx.tcx.lang_items().require(LangItem::IteratorNext).ok() == Some(id))`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `path_res(cx, expr).opt_def_id().map_or(false, |id| cx.tcx.lang_items().get(LangItem::IteratorNext) == Some(id))`
 
 error: use of a def path to a `LangItem`
   --> $DIR/unnecessary_def_path.rs:59:13
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
index af46d87bf67..2a240cc249b 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
@@ -1,10 +1,10 @@
-error: hardcoded path to a language item
-  --> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
+error: hardcoded path to a diagnostic item
+  --> $DIR/unnecessary_def_path_hardcoded_path.rs:10:36
    |
-LL |     const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"];
-   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: convert all references to use `LangItem::DerefMut`
+   = help: convert all references to use `sym::Deref`
    = note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
 
 error: hardcoded path to a diagnostic item
@@ -15,13 +15,13 @@ LL |     const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref",
    |
    = help: convert all references to use `sym::deref_method`
 
-error: hardcoded path to a diagnostic item
-  --> $DIR/unnecessary_def_path_hardcoded_path.rs:10:36
+error: hardcoded path to a language item
+  --> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
    |
-LL |     const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];
-   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"];
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: convert all references to use `sym::Deref`
+   = help: convert all references to use `LangItem::DerefMut`
 
 error: aborting due to 3 previous errors