about summary refs log tree commit diff
path: root/compiler/rustc_lint
diff options
context:
space:
mode:
authorArthur Lafrance <lafrancearthur@gmail.com>2023-09-25 00:15:00 -0700
committerArthur Lafrance <lafrancearthur@gmail.com>2023-10-16 19:47:33 -0700
commitf77dea89e183b638841d42d4d7bea48058a98e76 (patch)
tree18bc71a5132be3dc008d7b45af46d2664db28dff /compiler/rustc_lint
parent8769e02d0b17e18e0a52b521a82da4bcae2e6385 (diff)
downloadrust-f77dea89e183b638841d42d4d7bea48058a98e76.tar.gz
rust-f77dea89e183b638841d42d4d7bea48058a98e76.zip
basic lint v2 implemented
Diffstat (limited to 'compiler/rustc_lint')
-rw-r--r--compiler/rustc_lint/messages.ftl2
-rw-r--r--compiler/rustc_lint/src/internal.rs45
-rw-r--r--compiler/rustc_lint/src/lib.rs4
-rw-r--r--compiler/rustc_lint/src/lints.rs6
-rw-r--r--compiler/rustc_lint/src/span_use_eq_ctxt.rs38
5 files changed, 54 insertions, 41 deletions
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 197fe6552d7..261451e530e 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -494,6 +494,8 @@ lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}`
 
 lint_requested_level = requested on the command line with `{$level} {$lint_name}`
 
+lint_span_use_eq_ctxt = use `eq_ctxt()` not `ctxt() == ctxt()`
+
 lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target
     .label = target type is set here
 
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index fc2d3d0a254..c2aa768e945 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -3,14 +3,14 @@
 
 use crate::lints::{
     BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
-    QueryInstability, TyQualified, TykindDiag, TykindKind, UntranslatableDiag,
+    QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag, TykindKind, UntranslatableDiag,
     UntranslatableDiagnosticTrivial,
 };
 use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc_ast as ast;
 use rustc_hir::def::Res;
 use rustc_hir::{def_id::DefId, Expr, ExprKind, GenericArg, PatKind, Path, PathSegment, QPath};
-use rustc_hir::{HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind};
+use rustc_hir::{BinOp, BinOpKind, HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind};
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::hygiene::{ExpnKind, MacroKind};
@@ -537,3 +537,44 @@ impl LateLintPass<'_> for BadOptAccess {
         }
     }
 }
+
+// some things i'm not sure about:
+//   * is Warn the right level?
+//   * the way i verify that the right method is being called (path + diag item check)
+
+declare_tool_lint! {
+    pub rustc::SPAN_USE_EQ_CTXT,
+    Warn, // is this the right level?
+    "Use of `==` with `Span::ctxt` rather than `Span::eq_ctxt`",
+    report_in_external_macro: true
+}
+
+declare_lint_pass!(SpanUseEqCtxt => [SPAN_USE_EQ_CTXT]);
+
+impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
+        if let ExprKind::Binary(BinOp { node: BinOpKind::Eq, .. }, lhs, rhs) = expr.kind {
+            if is_span_ctxt_call(cx, lhs) && is_span_ctxt_call(cx, rhs) {
+                cx.emit_spanned_lint(
+                    SPAN_USE_EQ_CTXT,
+                    expr.span,
+                    SpanUseEqCtxtDiag { msg: "fail" },
+                );
+            }
+        }
+    }
+}
+
+fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    match &expr.kind {
+        ExprKind::MethodCall(path, receiver, _, _) => {
+            path.ident.name.as_str() == "ctxt"
+                && cx
+                    .typeck_results()
+                    .type_dependent_def_id(receiver.hir_id)
+                    .is_some_and(|did| cx.tcx.is_diagnostic_item(sym::Span, did))
+        }
+
+        _ => false,
+    }
+}
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index ca1f620b7c7..d61c59af1e0 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -83,7 +83,6 @@ mod passes;
 mod ptr_nulls;
 mod redundant_semicolon;
 mod reference_casting;
-mod span_use_eq_ctxt;
 mod traits;
 mod types;
 mod unused;
@@ -532,6 +531,8 @@ fn register_internals(store: &mut LintStore) {
     store.register_late_mod_pass(|_| Box::new(BadOptAccess));
     store.register_lints(&PassByValue::get_lints());
     store.register_late_mod_pass(|_| Box::new(PassByValue));
+    store.register_lints(&SpanUseEqCtxt::get_lints());
+    store.register_late_mod_pass(|_| Box::new(SpanUseEqCtxt));
     // FIXME(davidtwco): deliberately do not include `UNTRANSLATABLE_DIAGNOSTIC` and
     // `DIAGNOSTIC_OUTSIDE_OF_IMPL` here because `-Wrustc::internal` is provided to every crate and
     // these lints will trigger all of the time - change this once migration to diagnostic structs
@@ -549,6 +550,7 @@ fn register_internals(store: &mut LintStore) {
             LintId::of(USAGE_OF_QUALIFIED_TY),
             LintId::of(EXISTING_DOC_KEYWORD),
             LintId::of(BAD_OPT_ACCESS),
+            LintId::of(SPAN_USE_EQ_CTXT),
         ],
     );
 }
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 594ef97b3ff..a02bee506df 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -901,6 +901,12 @@ pub struct QueryInstability {
 }
 
 #[derive(LintDiagnostic)]
+#[diag(lint_span_use_eq_ctxt)]
+pub struct SpanUseEqCtxtDiag<'a> {
+    pub msg: &'a str,
+}
+
+#[derive(LintDiagnostic)]
 #[diag(lint_tykind_kind)]
 pub struct TykindKind {
     #[suggestion(code = "ty", applicability = "maybe-incorrect")]
diff --git a/compiler/rustc_lint/src/span_use_eq_ctxt.rs b/compiler/rustc_lint/src/span_use_eq_ctxt.rs
deleted file mode 100644
index 19fea01bf4f..00000000000
--- a/compiler/rustc_lint/src/span_use_eq_ctxt.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-use crate::{LateContext, LateLintPass};
-use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind};
-use rustc_span::sym;
-
-declare_lint! {
-    pub SPAN_USE_EQ_CTXT,
-    Warn, // is this the right level?
-    "Use of `==` with `Span::ctxt` rather than `Span::eq_ctxt`"
-}
-
-declare_lint_pass!(SpanUseEqCtxt => [SPAN_USE_EQ_CTXT]);
-
-impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
-        if let ExprKind::Binary(BinOp { node: BinOpKind::Eq, .. }, lhs, rhs) = expr.kind {
-            if is_span_ctxt_call(cx, lhs) && is_span_ctxt_call(cx, rhs) {
-                todo!(); // emit lint
-            }
-        }
-    }
-}
-
-fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    match &expr.kind {
-        ExprKind::MethodCall(..) => {
-            // i gave a method a diagnostic item -- FIXME: switch to a diagnostic
-            // item for the Span type and check:
-            //   * method call path == "ctxt"
-            //   * receiver type matches Span diag item
-            // also FIXME(todo) remove old SpanCtxt diagnostic item
-            cx.typeck_results()
-                .type_dependent_def_id(expr.hir_id)
-                .is_some_and(|did| cx.tcx.is_diagnostic_item(sym::SpanCtxt, did))
-        }
-
-        _ => false,
-    }
-}