Skip to content

Commit 5c06567

Browse files
committed
Add internal lints default_hash_types and usage_of_ty_tykind
1 parent c796b1f commit 5c06567

File tree

2 files changed

+166
-0
lines changed

2 files changed

+166
-0
lines changed

src/librustc/lint/internal.rs

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
// Copyright 2012-2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! Some lints that are only useful in the compiler or crates that use compiler internals, such as
12+
//! Clippy.
13+
14+
use errors::Applicability;
15+
use hir::{Expr, ExprKind, PatKind, Path, QPath, Ty, TyKind};
16+
use lint::{
17+
EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass,
18+
};
19+
use rustc_data_structures::fx::FxHashMap;
20+
use syntax::ast::Ident;
21+
22+
declare_lint! {
23+
pub DEFAULT_HASH_TYPES,
24+
Warn,
25+
"forbid HashMap and HashSet and suggest the FxHash* variants"
26+
}
27+
28+
pub struct DefaultHashTypes {
29+
map: FxHashMap<String, String>,
30+
}
31+
32+
impl DefaultHashTypes {
33+
pub fn new() -> Self {
34+
let mut map = FxHashMap::default();
35+
map.insert("HashMap".to_string(), "FxHashMap".to_string());
36+
map.insert("HashSet".to_string(), "FxHashSet".to_string());
37+
Self { map }
38+
}
39+
}
40+
41+
impl LintPass for DefaultHashTypes {
42+
fn get_lints(&self) -> LintArray {
43+
lint_array!(DEFAULT_HASH_TYPES)
44+
}
45+
}
46+
47+
impl EarlyLintPass for DefaultHashTypes {
48+
fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
49+
let ident_string = ident.to_string();
50+
if let Some(replace) = self.map.get(&ident_string) {
51+
let msg = format!(
52+
"Prefer {} over {}, it has better performance",
53+
replace, ident_string
54+
);
55+
let mut db = cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, &msg);
56+
db.span_suggestion_with_applicability(
57+
ident.span,
58+
"use",
59+
replace.to_string(),
60+
Applicability::MaybeIncorrect, // FxHashMap, ... needs another import
61+
);
62+
db.note(&format!(
63+
"a `use rustc_data_structures::fx::{}` may be necessary",
64+
replace
65+
))
66+
.emit();
67+
}
68+
}
69+
}
70+
71+
declare_lint! {
72+
pub USAGE_OF_TY_TYKIND,
73+
Warn,
74+
"Usage of `ty::TyKind` outside of the `ty::sty` module"
75+
}
76+
77+
pub struct TyKindUsage;
78+
79+
impl LintPass for TyKindUsage {
80+
fn get_lints(&self) -> LintArray {
81+
lint_array!(USAGE_OF_TY_TYKIND)
82+
}
83+
}
84+
85+
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyKindUsage {
86+
fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &'tcx Expr) {
87+
let qpaths = match &expr.node {
88+
ExprKind::Match(_, arms, _) => {
89+
let mut qpaths = vec![];
90+
for arm in arms {
91+
for pat in &arm.pats {
92+
match &pat.node {
93+
PatKind::Path(qpath) | PatKind::TupleStruct(qpath, ..) => {
94+
qpaths.push(qpath)
95+
}
96+
_ => (),
97+
}
98+
}
99+
}
100+
qpaths
101+
}
102+
ExprKind::Path(qpath) => vec![qpath],
103+
_ => vec![],
104+
};
105+
for qpath in qpaths {
106+
if let QPath::Resolved(_, path) = qpath {
107+
let segments_iter = path.segments.iter().rev().skip(1).rev();
108+
109+
if let Some(last) = segments_iter.clone().last() {
110+
if last.ident.as_str() == "TyKind" {
111+
let path = Path {
112+
span: path.span.with_hi(last.ident.span.hi()),
113+
def: path.def,
114+
segments: segments_iter.cloned().collect(),
115+
};
116+
117+
if let Some(def) = last.def {
118+
if def
119+
.def_id()
120+
.match_path(cx.tcx, &["rustc", "ty", "sty", "TyKind"])
121+
{
122+
cx.struct_span_lint(
123+
USAGE_OF_TY_TYKIND,
124+
path.span,
125+
"usage of `ty::TyKind::<kind>`",
126+
)
127+
.span_suggestion_with_applicability(
128+
path.span,
129+
"try using ty::<kind> directly",
130+
"ty".to_string(),
131+
Applicability::MaybeIncorrect, // ty maybe needs an import
132+
).emit();
133+
}
134+
}
135+
}
136+
}
137+
}
138+
}
139+
}
140+
141+
fn check_ty(&mut self, cx: &LateContext<'_, '_>, ty: &'tcx Ty) {
142+
if let TyKind::Path(qpath) = &ty.node {
143+
if let QPath::Resolved(_, path) = qpath {
144+
if let Some(last) = path.segments.iter().last() {
145+
if last.ident.as_str() == "TyKind" {
146+
if let Some(def) = last.def {
147+
if def
148+
.def_id()
149+
.match_path(cx.tcx, &["rustc", "ty", "sty", "TyKind"])
150+
{
151+
cx.struct_span_lint(
152+
USAGE_OF_TY_TYKIND,
153+
path.span,
154+
"usage of `ty::TyKind`",
155+
)
156+
.help("try using `ty::Ty` instead")
157+
.emit();
158+
}
159+
}
160+
}
161+
}
162+
}
163+
}
164+
}
165+
}

src/librustc/lint/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,7 @@ impl_stable_hash_for!(enum self::LintSource {
574574
pub type LevelSource = (Level, LintSource);
575575

576576
pub mod builtin;
577+
pub mod internal;
577578
mod context;
578579
mod levels;
579580

0 commit comments

Comments
 (0)