|
3 | 3 |
|
4 | 4 | use crate::lints::{
|
5 | 5 | BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
|
6 |
| - QueryInstability, TyQualified, TykindDiag, TykindKind, UntranslatableDiag, |
| 6 | + QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag, TykindKind, UntranslatableDiag, |
7 | 7 | UntranslatableDiagnosticTrivial,
|
8 | 8 | };
|
9 | 9 | use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
|
10 | 10 | use rustc_ast as ast;
|
11 | 11 | use rustc_hir::def::Res;
|
12 | 12 | use rustc_hir::{def_id::DefId, Expr, ExprKind, GenericArg, PatKind, Path, PathSegment, QPath};
|
13 |
| -use rustc_hir::{HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind}; |
| 13 | +use rustc_hir::{BinOp, BinOpKind, HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind}; |
14 | 14 | use rustc_middle::ty;
|
15 | 15 | use rustc_session::{declare_lint_pass, declare_tool_lint};
|
16 | 16 | use rustc_span::hygiene::{ExpnKind, MacroKind};
|
@@ -537,3 +537,44 @@ impl LateLintPass<'_> for BadOptAccess {
|
537 | 537 | }
|
538 | 538 | }
|
539 | 539 | }
|
| 540 | + |
| 541 | +// some things i'm not sure about: |
| 542 | +// * is Warn the right level? |
| 543 | +// * the way i verify that the right method is being called (path + diag item check) |
| 544 | + |
| 545 | +declare_tool_lint! { |
| 546 | + pub rustc::SPAN_USE_EQ_CTXT, |
| 547 | + Warn, // is this the right level? |
| 548 | + "Use of `==` with `Span::ctxt` rather than `Span::eq_ctxt`", |
| 549 | + report_in_external_macro: true |
| 550 | +} |
| 551 | + |
| 552 | +declare_lint_pass!(SpanUseEqCtxt => [SPAN_USE_EQ_CTXT]); |
| 553 | + |
| 554 | +impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt { |
| 555 | + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { |
| 556 | + if let ExprKind::Binary(BinOp { node: BinOpKind::Eq, .. }, lhs, rhs) = expr.kind { |
| 557 | + if is_span_ctxt_call(cx, lhs) && is_span_ctxt_call(cx, rhs) { |
| 558 | + cx.emit_spanned_lint( |
| 559 | + SPAN_USE_EQ_CTXT, |
| 560 | + expr.span, |
| 561 | + SpanUseEqCtxtDiag { msg: "fail" }, |
| 562 | + ); |
| 563 | + } |
| 564 | + } |
| 565 | + } |
| 566 | +} |
| 567 | + |
| 568 | +fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { |
| 569 | + match &expr.kind { |
| 570 | + ExprKind::MethodCall(path, receiver, _, _) => { |
| 571 | + path.ident.name.as_str() == "ctxt" |
| 572 | + && cx |
| 573 | + .typeck_results() |
| 574 | + .type_dependent_def_id(receiver.hir_id) |
| 575 | + .is_some_and(|did| cx.tcx.is_diagnostic_item(sym::Span, did)) |
| 576 | + } |
| 577 | + |
| 578 | + _ => false, |
| 579 | + } |
| 580 | +} |
0 commit comments