1 //! Some lints that are only useful in the compiler or crates that use compiler internals, such as
4 use crate::hir::{Expr, ExprKind, PatKind, Path, QPath, Ty, TyKind};
6 EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass,
8 use errors::Applicability;
9 use rustc_data_structures::fx::FxHashMap;
10 use syntax::ast::Ident;
13 pub DEFAULT_HASH_TYPES,
15 "forbid HashMap and HashSet and suggest the FxHash* variants"
18 pub struct DefaultHashTypes {
19 map: FxHashMap<String, String>,
22 impl DefaultHashTypes {
23 pub fn new() -> Self {
24 let mut map = FxHashMap::default();
25 map.insert("HashMap".to_string(), "FxHashMap".to_string());
26 map.insert("HashSet".to_string(), "FxHashSet".to_string());
31 impl LintPass for DefaultHashTypes {
32 fn get_lints(&self) -> LintArray {
33 lint_array!(DEFAULT_HASH_TYPES)
36 fn name(&self) -> &'static str {
41 impl EarlyLintPass for DefaultHashTypes {
42 fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
43 let ident_string = ident.to_string();
44 if let Some(replace) = self.map.get(&ident_string) {
46 "Prefer {} over {}, it has better performance",
49 let mut db = cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, &msg);
54 Applicability::MaybeIncorrect, // FxHashMap, ... needs another import
57 "a `use rustc_data_structures::fx::{}` may be necessary",
66 pub USAGE_OF_TY_TYKIND,
68 "Usage of `ty::TyKind` outside of the `ty::sty` module"
71 pub struct TyKindUsage;
73 impl LintPass for TyKindUsage {
74 fn get_lints(&self) -> LintArray {
75 lint_array!(USAGE_OF_TY_TYKIND)
78 fn name(&self) -> &'static str {
83 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyKindUsage {
84 fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &'tcx Expr) {
85 let qpaths = match &expr.node {
86 ExprKind::Match(_, arms, _) => {
87 let mut qpaths = vec![];
89 for pat in &arm.pats {
91 PatKind::Path(qpath) | PatKind::TupleStruct(qpath, ..) => {
100 ExprKind::Path(qpath) => vec![qpath],
103 for qpath in qpaths {
104 if let QPath::Resolved(_, path) = qpath {
105 let segments_iter = path.segments.iter().rev().skip(1).rev();
107 if let Some(last) = segments_iter.clone().last() {
108 if last.ident.as_str() == "TyKind" {
110 span: path.span.with_hi(last.ident.span.hi()),
112 segments: segments_iter.cloned().collect(),
115 if let Some(def) = last.def {
118 .match_path(cx.tcx, &["rustc", "ty", "sty", "TyKind"])
123 "usage of `ty::TyKind::<kind>`",
127 "try using ty::<kind> directly",
129 Applicability::MaybeIncorrect, // ty maybe needs an import
140 fn check_ty(&mut self, cx: &LateContext<'_, '_>, ty: &'tcx Ty) {
141 if let TyKind::Path(qpath) = &ty.node {
142 if let QPath::Resolved(_, path) = qpath {
143 if let Some(last) = path.segments.iter().last() {
144 if last.ident.as_str() == "TyKind" {
145 if let Some(def) = last.def {
148 .match_path(cx.tcx, &["rustc", "ty", "sty", "TyKind"])
153 "usage of `ty::TyKind`",
155 .help("try using `ty::Ty` instead")