1
Fork 0

Implement lint against Symbol::intern on a string literal

This commit is contained in:
clubby789 2024-11-27 17:21:59 +00:00
parent c322cd5c5a
commit 72d2db7bf4
6 changed files with 54 additions and 2 deletions

View file

@ -17,8 +17,9 @@ use tracing::debug;
use crate::lints::{
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag, TyQualified,
TykindDiag, TykindKind, TypeIrInherentUsage, UntranslatableDiag,
NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag,
SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrInherentUsage,
UntranslatableDiag,
};
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
@ -657,3 +658,33 @@ fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
_ => false,
}
}
declare_tool_lint! {
/// The `symbol_intern_string_literal` detects `Symbol::intern` being called on a string literal
pub rustc::SYMBOL_INTERN_STRING_LITERAL,
// rustc_driver crates out of the compiler can't/shouldn't add preinterned symbols;
// bootstrap will deny this manually
Allow,
"Forbid uses of string literals in `Symbol::intern`, suggesting preinterning instead",
report_in_external_macro: true
}
declare_lint_pass!(SymbolInternStringLiteral => [SYMBOL_INTERN_STRING_LITERAL]);
impl<'tcx> LateLintPass<'tcx> for SymbolInternStringLiteral {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
if let ExprKind::Call(path, [arg]) = expr.kind
&& let ExprKind::Path(ref qpath) = path.kind
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
&& cx.tcx.is_diagnostic_item(sym::SymbolIntern, def_id)
&& let ExprKind::Lit(kind) = arg.kind
&& let rustc_ast::LitKind::Str(_, _) = kind.node
{
cx.emit_span_lint(
SYMBOL_INTERN_STRING_LITERAL,
kind.span,
SymbolInternStringLiteralDiag,
);
}
}
}

View file

@ -614,6 +614,8 @@ fn register_internals(store: &mut LintStore) {
store.register_late_mod_pass(|_| Box::new(PassByValue));
store.register_lints(&SpanUseEqCtxt::lint_vec());
store.register_late_mod_pass(|_| Box::new(SpanUseEqCtxt));
store.register_lints(&SymbolInternStringLiteral::lint_vec());
store.register_late_mod_pass(|_| Box::new(SymbolInternStringLiteral));
// 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

View file

@ -907,6 +907,11 @@ pub(crate) struct QueryUntracked {
#[diag(lint_span_use_eq_ctxt)]
pub(crate) struct SpanUseEqCtxtDiag;
#[derive(LintDiagnostic)]
#[diag(lint_symbol_intern_string_literal)]
#[help]
pub(crate) struct SymbolInternStringLiteralDiag;
#[derive(LintDiagnostic)]
#[diag(lint_tykind_kind)]
pub(crate) struct TykindKind {