Skip to content

Commit e4190a7

Browse files
committed
Implement lint against Symbol::intern on a string literal
1 parent c322cd5 commit e4190a7

File tree

5 files changed

+45
-2
lines changed

5 files changed

+45
-2
lines changed

compiler/rustc_lint/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,9 @@ lint_suspicious_double_ref_clone =
772772
lint_suspicious_double_ref_deref =
773773
using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type
774774
775+
lint_symbol_intern_string_literal = using `Symbol::intern` on a string literal
776+
.help = consider adding the symbol to `compiler/rustc_span/src/symbol.rs`
777+
775778
lint_trailing_semi_macro = trailing semicolon in macro used in expression position
776779
.note1 = macro invocations at the end of a block are treated as expressions
777780
.note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}`

compiler/rustc_lint/src/internal.rs

+33-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ use tracing::debug;
1717

1818
use crate::lints::{
1919
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
20-
NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag, TyQualified,
21-
TykindDiag, TykindKind, TypeIrInherentUsage, UntranslatableDiag,
20+
NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag,
21+
SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrInherentUsage,
22+
UntranslatableDiag,
2223
};
2324
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
2425

@@ -657,3 +658,33 @@ fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
657658
_ => false,
658659
}
659660
}
661+
662+
declare_tool_lint! {
663+
pub rustc::SYMBOL_INTERN_STRING_LITERAL,
664+
Warn,
665+
"Forbid uses of string literals in `Symbol::intern`, suggesting preinterning instead",
666+
report_in_external_macro: true
667+
}
668+
669+
declare_lint_pass!(SymbolInternStringLiteral => [SYMBOL_INTERN_STRING_LITERAL]);
670+
671+
impl<'tcx> LateLintPass<'tcx> for SymbolInternStringLiteral {
672+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
673+
if cx.tcx.sess.is_test_crate() {
674+
return;
675+
}
676+
if let ExprKind::Call(path, [arg]) = expr.kind
677+
&& let ExprKind::Path(ref qpath) = path.kind
678+
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
679+
&& cx.tcx.is_diagnostic_item(sym::SymbolIntern, def_id)
680+
&& let ExprKind::Lit(kind) = arg.kind
681+
&& let rustc_ast::LitKind::Str(_, _) = kind.node
682+
{
683+
cx.emit_span_lint(
684+
SYMBOL_INTERN_STRING_LITERAL,
685+
kind.span,
686+
SymbolInternStringLiteralDiag,
687+
);
688+
}
689+
}
690+
}

compiler/rustc_lint/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,8 @@ fn register_internals(store: &mut LintStore) {
614614
store.register_late_mod_pass(|_| Box::new(PassByValue));
615615
store.register_lints(&SpanUseEqCtxt::lint_vec());
616616
store.register_late_mod_pass(|_| Box::new(SpanUseEqCtxt));
617+
store.register_lints(&SymbolInternStringLiteral::lint_vec());
618+
store.register_late_mod_pass(|_| Box::new(SymbolInternStringLiteral));
617619
// FIXME(davidtwco): deliberately do not include `UNTRANSLATABLE_DIAGNOSTIC` and
618620
// `DIAGNOSTIC_OUTSIDE_OF_IMPL` here because `-Wrustc::internal` is provided to every crate and
619621
// these lints will trigger all of the time - change this once migration to diagnostic structs

compiler/rustc_lint/src/lints.rs

+5
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,11 @@ pub(crate) struct QueryUntracked {
907907
#[diag(lint_span_use_eq_ctxt)]
908908
pub(crate) struct SpanUseEqCtxtDiag;
909909

910+
#[derive(LintDiagnostic)]
911+
#[diag(lint_symbol_intern_string_literal)]
912+
#[help]
913+
pub(crate) struct SymbolInternStringLiteralDiag;
914+
910915
#[derive(LintDiagnostic)]
911916
#[diag(lint_tykind_kind)]
912917
pub(crate) struct TykindKind {

compiler/rustc_span/src/symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ symbols! {
315315
StructuralPartialEq,
316316
SubdiagMessage,
317317
Subdiagnostic,
318+
SymbolIntern,
318319
Sync,
319320
SyncUnsafeCell,
320321
T,
@@ -2401,6 +2402,7 @@ impl Symbol {
24012402
}
24022403

24032404
/// Maps a string to its interned representation.
2405+
#[rustc_diagnostic_item = "SymbolIntern"]
24042406
pub fn intern(string: &str) -> Self {
24052407
with_session_globals(|session_globals| session_globals.symbol_interner.intern(string))
24062408
}

0 commit comments

Comments
 (0)