Skip to content

Commit 307610c

Browse files
committed
Add internal lint against Ty == Ty
This operation does not do what people usually want. Also check against other comparison operators since they are just as sketchy. Allow the `ty_eq_operator` lint for now until the next bootstrap bump
1 parent 4331c15 commit 307610c

File tree

7 files changed

+165
-10
lines changed

7 files changed

+165
-10
lines changed

compiler/rustc_lint/messages.ftl

+7
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,13 @@ lint_suspicious_double_ref_deref =
505505
506506
lint_trivial_untranslatable_diag = diagnostic with static strings only
507507
508+
509+
lint_ty_compare_operator_used = using the a comparison operator on `Ty`
510+
.note = this does probably not what you want as it does not handle inference variables and more
511+
.help = for more information, see https://rustc-dev-guide.rust-lang.org/ty.html#comparing-types
512+
513+
lint_ty_no_compare_operator_for_diagnostics = it's also not recommended to use it for diagnostics
514+
508515
lint_ty_qualified = usage of qualified `ty::{$ty}`
509516
.suggestion = try importing it and using it unqualified
510517

compiler/rustc_lint/src/internal.rs

+36-9
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
44
use crate::lints::{
55
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
6-
QueryInstability, TyQualified, TykindDiag, TykindKind, UntranslatableDiag,
7-
UntranslatableDiagnosticTrivial,
6+
QueryInstability, TyCompareOperatorUsed, TyQualified, TykindDiag, TykindKind,
7+
UntranslatableDiag, UntranslatableDiagnosticTrivial,
88
};
99
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
1010
use rustc_ast as ast;
11+
use rustc_hir as hir;
1112
use rustc_hir::def::Res;
1213
use rustc_hir::{def_id::DefId, Expr, ExprKind, GenericArg, PatKind, Path, PathSegment, QPath};
1314
use rustc_hir::{HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind};
@@ -127,12 +128,7 @@ declare_lint_pass!(TyTyKind => [
127128
]);
128129

129130
impl<'tcx> LateLintPass<'tcx> for TyTyKind {
130-
fn check_path(
131-
&mut self,
132-
cx: &LateContext<'tcx>,
133-
path: &rustc_hir::Path<'tcx>,
134-
_: rustc_hir::HirId,
135-
) {
131+
fn check_path(&mut self, cx: &LateContext<'tcx>, path: &hir::Path<'tcx>, _: hir::HirId) {
136132
if let Some(segment) = path.segments.iter().nth_back(1)
137133
&& lint_ty_kind_usage(cx, &segment.res)
138134
{
@@ -269,6 +265,37 @@ fn gen_args(segment: &PathSegment<'_>) -> String {
269265
String::new()
270266
}
271267

268+
declare_tool_lint! {
269+
pub rustc::TY_COMPARE_OPERATOR,
270+
Allow,
271+
"using the a comparison operator on `Ty`"
272+
}
273+
274+
declare_lint_pass!(TyCompareOperator => [TY_COMPARE_OPERATOR]);
275+
276+
impl<'tcx> LateLintPass<'tcx> for TyCompareOperator {
277+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
278+
use hir::BinOpKind::*;
279+
280+
if let hir::ExprKind::Binary(
281+
hir::BinOp { node:Eq | Ne | Gt | Lt | Le | Ge, span},
282+
lhs,
283+
rhs
284+
) = expr.kind
285+
&& let ty::Adt(lhs_def, _) = cx.typeck_results().node_type(lhs.hir_id).peel_refs().kind()
286+
&& let ty::Adt(rhs_def, _) = cx.typeck_results().node_type(rhs.hir_id).peel_refs().kind()
287+
&& cx.tcx.is_diagnostic_item(sym::Ty, lhs_def.did())
288+
&& cx.tcx.is_diagnostic_item(sym::Ty, rhs_def.did())
289+
{
290+
cx.emit_spanned_lint(
291+
TY_COMPARE_OPERATOR,
292+
span,
293+
TyCompareOperatorUsed,
294+
)
295+
}
296+
}
297+
}
298+
272299
declare_tool_lint! {
273300
/// The `lint_pass_impl_without_macro` detects manual implementations of a lint
274301
/// pass, without using [`declare_lint_pass`] or [`impl_lint_pass`].
@@ -318,7 +345,7 @@ fn is_doc_keyword(s: Symbol) -> bool {
318345
}
319346

320347
impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword {
321-
fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) {
348+
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
322349
for attr in cx.tcx.hir().attrs(item.hir_id()) {
323350
if !attr.has_name(sym::doc) {
324351
continue;

compiler/rustc_lint/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,8 @@ fn register_internals(store: &mut LintStore) {
524524
store.register_late_mod_pass(|_| Box::new(ExistingDocKeyword));
525525
store.register_lints(&TyTyKind::get_lints());
526526
store.register_late_mod_pass(|_| Box::new(TyTyKind));
527+
store.register_lints(&TyCompareOperator::get_lints());
528+
store.register_late_mod_pass(|_| Box::new(TyCompareOperator));
527529
store.register_lints(&Diagnostics::get_lints());
528530
store.register_early_pass(|| Box::new(Diagnostics));
529531
store.register_late_mod_pass(|_| Box::new(Diagnostics));
@@ -543,6 +545,7 @@ fn register_internals(store: &mut LintStore) {
543545
LintId::of(DEFAULT_HASH_TYPES),
544546
LintId::of(POTENTIAL_QUERY_INSTABILITY),
545547
LintId::of(USAGE_OF_TY_TYKIND),
548+
LintId::of(TY_COMPARE_OPERATOR),
546549
LintId::of(PASS_BY_VALUE),
547550
LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
548551
LintId::of(USAGE_OF_QUALIFIED_TY),

compiler/rustc_lint/src/lints.rs

+7
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,13 @@ pub struct TyQualified {
920920
pub suggestion: Span,
921921
}
922922

923+
#[derive(LintDiagnostic)]
924+
#[diag(lint_ty_compare_operator_used)]
925+
#[note]
926+
#[note(lint_ty_no_compare_operator_for_diagnostics)]
927+
#[help]
928+
pub struct TyCompareOperatorUsed;
929+
923930
#[derive(LintDiagnostic)]
924931
#[diag(lint_lintpass_by_hand)]
925932
#[help]

src/bootstrap/builder.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -1878,9 +1878,16 @@ impl<'a> Builder<'a> {
18781878
rustdocflags.arg("-Wrustdoc::invalid_codeblock_attributes");
18791879
}
18801880

1881-
if mode == Mode::Rustc {
1881+
if mode == Mode::Rustc || mode == Mode::ToolRustc {
18821882
rustflags.arg("-Zunstable-options");
18831883
rustflags.arg("-Wrustc::internal");
1884+
1885+
// #[cfg(not(bootstrap))]
1886+
if stage != 0 {
1887+
// FIXME(Nilstrieb): Allow this lint for now.
1888+
// After it's in beta, we can start work on fixing it.
1889+
rustflags.arg("-Arustc::ty-compare-operator");
1890+
}
18841891
}
18851892

18861893
// Throughout the build Cargo can execute a number of build scripts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// compile-flags: -Z unstable-options
2+
3+
#![feature(rustc_attrs)]
4+
#![forbid(rustc::ty_compare_operator)]
5+
6+
mod ty1 {
7+
#[derive(PartialEq, PartialOrd)]
8+
#[rustc_diagnostic_item = "Ty"]
9+
pub struct Ty;
10+
}
11+
12+
mod ty2 {
13+
#[derive(PartialEq, PartialOrd)]
14+
pub struct Ty;
15+
}
16+
17+
fn main() {
18+
let _ = ty1::Ty == ty1::Ty;
19+
//~^ ERROR using the a comparison operator on `Ty`
20+
let _ = ty1::Ty != ty1::Ty;
21+
//~^ ERROR using the a comparison operator on `Ty`
22+
let _ = ty1::Ty < ty1::Ty;
23+
//~^ ERROR using the a comparison operator on `Ty`
24+
let _ = ty1::Ty <= ty1::Ty;
25+
//~^ ERROR using the a comparison operator on `Ty`
26+
let _ = ty1::Ty > ty1::Ty;
27+
//~^ ERROR using the a comparison operator on `Ty`
28+
let _ = ty1::Ty >= ty1::Ty;
29+
//~^ ERROR using the a comparison operator on `Ty`
30+
31+
let _ = ty2::Ty == ty2::Ty;
32+
let _ = ty2::Ty != ty2::Ty;
33+
let _ = ty2::Ty < ty2::Ty;
34+
let _ = ty2::Ty <= ty2::Ty;
35+
let _ = ty2::Ty > ty2::Ty;
36+
let _ = ty2::Ty >= ty2::Ty;
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
error: using the a comparison operator on `Ty`
2+
--> $DIR/ty_compare_operator.rs:18:21
3+
|
4+
LL | let _ = ty1::Ty == ty1::Ty;
5+
| ^^
6+
|
7+
= note: this does probably not what you want as it does not handle inference variables and more
8+
= note: it's also not recommended to use it for diagnostics
9+
= help: for more information, see https://rustc-dev-guide.rust-lang.org/ty.html#comparing-types
10+
note: the lint level is defined here
11+
--> $DIR/ty_compare_operator.rs:4:11
12+
|
13+
LL | #![forbid(rustc::ty_compare_operator)]
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
15+
16+
error: using the a comparison operator on `Ty`
17+
--> $DIR/ty_compare_operator.rs:20:21
18+
|
19+
LL | let _ = ty1::Ty != ty1::Ty;
20+
| ^^
21+
|
22+
= note: this does probably not what you want as it does not handle inference variables and more
23+
= note: it's also not recommended to use it for diagnostics
24+
= help: for more information, see https://rustc-dev-guide.rust-lang.org/ty.html#comparing-types
25+
26+
error: using the a comparison operator on `Ty`
27+
--> $DIR/ty_compare_operator.rs:22:21
28+
|
29+
LL | let _ = ty1::Ty < ty1::Ty;
30+
| ^
31+
|
32+
= note: this does probably not what you want as it does not handle inference variables and more
33+
= note: it's also not recommended to use it for diagnostics
34+
= help: for more information, see https://rustc-dev-guide.rust-lang.org/ty.html#comparing-types
35+
36+
error: using the a comparison operator on `Ty`
37+
--> $DIR/ty_compare_operator.rs:24:21
38+
|
39+
LL | let _ = ty1::Ty <= ty1::Ty;
40+
| ^^
41+
|
42+
= note: this does probably not what you want as it does not handle inference variables and more
43+
= note: it's also not recommended to use it for diagnostics
44+
= help: for more information, see https://rustc-dev-guide.rust-lang.org/ty.html#comparing-types
45+
46+
error: using the a comparison operator on `Ty`
47+
--> $DIR/ty_compare_operator.rs:26:21
48+
|
49+
LL | let _ = ty1::Ty > ty1::Ty;
50+
| ^
51+
|
52+
= note: this does probably not what you want as it does not handle inference variables and more
53+
= note: it's also not recommended to use it for diagnostics
54+
= help: for more information, see https://rustc-dev-guide.rust-lang.org/ty.html#comparing-types
55+
56+
error: using the a comparison operator on `Ty`
57+
--> $DIR/ty_compare_operator.rs:28:21
58+
|
59+
LL | let _ = ty1::Ty >= ty1::Ty;
60+
| ^^
61+
|
62+
= note: this does probably not what you want as it does not handle inference variables and more
63+
= note: it's also not recommended to use it for diagnostics
64+
= help: for more information, see https://rustc-dev-guide.rust-lang.org/ty.html#comparing-types
65+
66+
error: aborting due to 6 previous errors
67+

0 commit comments

Comments
 (0)