|  | use clippy_utils::diagnostics::span_lint; | 
|  | use rustc_ast::ast::{Item, ItemKind, UseTree, UseTreeKind}; | 
|  | use rustc_lint::{EarlyContext, EarlyLintPass}; | 
|  | use rustc_session::declare_lint_pass; | 
|  | use rustc_span::Span; | 
|  | use rustc_span::symbol::Ident; | 
|  |  | 
|  | declare_clippy_lint! { | 
|  | /// ### What it does | 
|  | /// Checks for imports that remove "unsafe" from an item's | 
|  | /// name. | 
|  | /// | 
|  | /// ### Why is this bad? | 
|  | /// Renaming makes it less clear which traits and | 
|  | /// structures are unsafe. | 
|  | /// | 
|  | /// ### Example | 
|  | /// ```rust,ignore | 
|  | /// use std::cell::{UnsafeCell as TotallySafeCell}; | 
|  | /// | 
|  | /// extern crate crossbeam; | 
|  | /// use crossbeam::{spawn_unsafe as spawn}; | 
|  | /// ``` | 
|  | #[clippy::version = "pre 1.29.0"] | 
|  | pub UNSAFE_REMOVED_FROM_NAME, | 
|  | style, | 
|  | "`unsafe` removed from API names on import" | 
|  | } | 
|  |  | 
|  | declare_lint_pass!(UnsafeNameRemoval => [UNSAFE_REMOVED_FROM_NAME]); | 
|  |  | 
|  | impl EarlyLintPass for UnsafeNameRemoval { | 
|  | fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { | 
|  | if let ItemKind::Use(ref use_tree) = item.kind { | 
|  | check_use_tree(use_tree, cx, item.span); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext<'_>, span: Span) { | 
|  | match use_tree.kind { | 
|  | UseTreeKind::Simple(Some(new_name)) => { | 
|  | let old_name = use_tree | 
|  | .prefix | 
|  | .segments | 
|  | .last() | 
|  | .expect("use paths cannot be empty") | 
|  | .ident; | 
|  | unsafe_to_safe_check(old_name, new_name, cx, span); | 
|  | }, | 
|  | UseTreeKind::Simple(None) | UseTreeKind::Glob => {}, | 
|  | UseTreeKind::Nested { ref items, .. } => { | 
|  | for (use_tree, _) in items { | 
|  | check_use_tree(use_tree, cx, span); | 
|  | } | 
|  | }, | 
|  | } | 
|  | } | 
|  |  | 
|  | fn unsafe_to_safe_check(old_name: Ident, new_name: Ident, cx: &EarlyContext<'_>, span: Span) { | 
|  | let old_str = old_name.name.as_str(); | 
|  | let new_str = new_name.name.as_str(); | 
|  | if contains_unsafe(old_str) && !contains_unsafe(new_str) { | 
|  | span_lint( | 
|  | cx, | 
|  | UNSAFE_REMOVED_FROM_NAME, | 
|  | span, | 
|  | format!("removed `unsafe` from the name of `{old_str}` in use as `{new_str}`"), | 
|  | ); | 
|  | } | 
|  | } | 
|  |  | 
|  | #[must_use] | 
|  | fn contains_unsafe(name: &str) -> bool { | 
|  | name.contains("Unsafe") || name.contains("unsafe") | 
|  | } |