Skip to content

Commit 747d288

Browse files
committed
Implement internal lints
- USAGE_OF_QUALIFIED_TY - TY_PASS_BY_REFERENCE
1 parent bdfdbcd commit 747d288

File tree

3 files changed

+126
-12
lines changed

3 files changed

+126
-12
lines changed

src/librustc/lint/internal.rs

Lines changed: 122 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Some lints that are only useful in the compiler or crates that use compiler internals, such as
22
//! Clippy.
33
4-
use crate::hir::{HirId, Path, PathSegment, QPath, Ty, TyKind};
4+
use crate::hir::{GenericArg, HirId, MutTy, Mutability, Path, PathSegment, QPath, Ty, TyKind};
55
use crate::lint::{
66
EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass,
77
};
@@ -57,12 +57,28 @@ impl EarlyLintPass for DefaultHashTypes {
5757
declare_lint! {
5858
pub USAGE_OF_TY_TYKIND,
5959
Allow,
60-
"Usage of `ty::TyKind` outside of the `ty::sty` module"
60+
"usage of `ty::TyKind` outside of the `ty::sty` module"
6161
}
6262

63-
declare_lint_pass!(TyKindUsage => [USAGE_OF_TY_TYKIND]);
63+
declare_lint! {
64+
pub TY_PASS_BY_REFERENCE,
65+
Allow,
66+
"passing `Ty` or `TyCtxt` by reference"
67+
}
68+
69+
declare_lint! {
70+
pub USAGE_OF_QUALIFIED_TY,
71+
Allow,
72+
"using `ty::{Ty,TyCtxt}` instead of importing it"
73+
}
74+
75+
declare_lint_pass!(TyTyKind => [
76+
USAGE_OF_TY_TYKIND,
77+
TY_PASS_BY_REFERENCE,
78+
USAGE_OF_QUALIFIED_TY,
79+
]);
6480

65-
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyKindUsage {
81+
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind {
6682
fn check_path(&mut self, cx: &LateContext<'_, '_>, path: &'tcx Path, _: HirId) {
6783
let segments = path.segments.iter().rev().skip(1).rev();
6884

@@ -82,16 +98,72 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyKindUsage {
8298
}
8399

84100
fn check_ty(&mut self, cx: &LateContext<'_, '_>, ty: &'tcx Ty) {
85-
if let TyKind::Path(qpath) = &ty.node {
86-
if let QPath::Resolved(_, path) = qpath {
87-
if let Some(last) = path.segments.iter().last() {
88-
if lint_ty_kind_usage(cx, last) {
89-
cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, "usage of `ty::TyKind`")
90-
.help("try using `ty::Ty` instead")
101+
match &ty.node {
102+
TyKind::Path(qpath) => {
103+
if let QPath::Resolved(_, path) = qpath {
104+
if let Some(last) = path.segments.iter().last() {
105+
if lint_ty_kind_usage(cx, last) {
106+
cx.struct_span_lint(
107+
USAGE_OF_TY_TYKIND,
108+
path.span,
109+
"usage of `ty::TyKind`",
110+
)
111+
.help("try using `Ty` instead")
91112
.emit();
113+
} else {
114+
if ty.span.ctxt().outer().expn_info().is_some() {
115+
return;
116+
}
117+
if let Some(t) = is_ty_or_ty_ctxt(cx, ty) {
118+
if path.segments.len() > 1 {
119+
cx.struct_span_lint(
120+
USAGE_OF_QUALIFIED_TY,
121+
path.span,
122+
&format!("usage of qualified `ty::{}`", t),
123+
)
124+
.span_suggestion(
125+
path.span,
126+
"try using it unqualified",
127+
t,
128+
// The import probably needs to be changed
129+
Applicability::MaybeIncorrect,
130+
)
131+
.emit();
132+
}
133+
}
134+
}
135+
}
136+
}
137+
}
138+
TyKind::Rptr(
139+
_,
140+
MutTy {
141+
ty: inner_ty,
142+
mutbl: Mutability::MutImmutable,
143+
},
144+
) => {
145+
if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner_def_id()) {
146+
if cx.tcx.impl_trait_ref(impl_did).is_some() {
147+
return;
92148
}
93149
}
150+
if let Some(t) = is_ty_or_ty_ctxt(cx, &inner_ty) {
151+
cx.struct_span_lint(
152+
TY_PASS_BY_REFERENCE,
153+
ty.span,
154+
&format!("passing `{}` by reference", t),
155+
)
156+
.span_suggestion(
157+
ty.span,
158+
"try passing by value",
159+
t,
160+
// Changing type of function argument
161+
Applicability::MaybeIncorrect,
162+
)
163+
.emit();
164+
}
94165
}
166+
_ => {}
95167
}
96168
}
97169
}
@@ -107,3 +179,43 @@ fn lint_ty_kind_usage(cx: &LateContext<'_, '_>, segment: &PathSegment) -> bool {
107179

108180
false
109181
}
182+
183+
fn is_ty_or_ty_ctxt(cx: &LateContext<'_, '_>, ty: &Ty) -> Option<String> {
184+
match &ty.node {
185+
TyKind::Path(qpath) => {
186+
if let QPath::Resolved(_, path) = qpath {
187+
let did = path.def.opt_def_id()?;
188+
if cx.match_def_path(did, &["rustc", "ty", "Ty"]) {
189+
return Some(format!("Ty{}", gen_args(path.segments.last().unwrap())));
190+
} else if cx.match_def_path(did, &["rustc", "ty", "context", "TyCtxt"]) {
191+
return Some(format!("TyCtxt{}", gen_args(path.segments.last().unwrap())));
192+
}
193+
}
194+
}
195+
_ => {}
196+
}
197+
198+
None
199+
}
200+
201+
fn gen_args(segment: &PathSegment) -> String {
202+
if let Some(args) = &segment.args {
203+
let lifetimes = args
204+
.args
205+
.iter()
206+
.filter_map(|arg| {
207+
if let GenericArg::Lifetime(lt) = arg {
208+
Some(lt.name.ident().to_string())
209+
} else {
210+
None
211+
}
212+
})
213+
.collect::<Vec<_>>();
214+
215+
if !lifetimes.is_empty() {
216+
return format!("<{}>", lifetimes.join(", "));
217+
}
218+
}
219+
220+
String::new()
221+
}

src/librustc_lint/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
495495

496496
pub fn register_internals(store: &mut lint::LintStore, sess: Option<&Session>) {
497497
store.register_early_pass(sess, false, false, box DefaultHashTypes::new());
498-
store.register_late_pass(sess, false, false, false, box TyKindUsage);
498+
store.register_late_pass(sess, false, false, false, box TyTyKind);
499499
store.register_group(
500500
sess,
501501
false,
@@ -504,6 +504,8 @@ pub fn register_internals(store: &mut lint::LintStore, sess: Option<&Session>) {
504504
vec![
505505
LintId::of(DEFAULT_HASH_TYPES),
506506
LintId::of(USAGE_OF_TY_TYKIND),
507+
LintId::of(TY_PASS_BY_REFERENCE),
508+
LintId::of(USAGE_OF_QUALIFIED_TY),
507509
],
508510
);
509511
}

src/librustc_mir/borrow_check/borrow_set.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ impl<'a, 'gcx, 'tcx> GatherBorrows<'a, 'gcx, 'tcx> {
315315
start_location, assigned_place, borrow_index,
316316
);
317317

318-
if !allow_two_phase_borrow(&self.tcx, kind) {
318+
if !allow_two_phase_borrow(self.tcx, kind) {
319319
debug!(" -> {:?}", start_location);
320320
return;
321321
}

0 commit comments

Comments
 (0)