Rollup merge of #133545 - clubby789:symbol-intern-lit, r=jieyouxu
Lint against Symbol::intern on a string literal Disabled in tests where this doesn't make much sense
This commit is contained in:
commit
453a1a8b7f
20 changed files with 94 additions and 37 deletions
|
@ -4,9 +4,9 @@ use rustc_ast::{NodeId, PatKind, attr, token};
|
|||
use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features, GateIssue};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::symbol::{Symbol, sym};
|
||||
use rustc_target::spec::abi;
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
|
@ -695,6 +695,7 @@ fn check_new_solver_banned_features(sess: &Session, features: &Features) {
|
|||
.find(|feat| feat.gate_name == sym::generic_const_exprs)
|
||||
.map(|feat| feat.attr_sp)
|
||||
{
|
||||
#[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
|
||||
sess.dcx().emit_err(errors::IncompatibleFeatures {
|
||||
spans: vec![gce_span],
|
||||
f1: Symbol::intern("-Znext-solver=globally"),
|
||||
|
|
|
@ -33,8 +33,8 @@ use rustc_middle::ty::{
|
|||
TyCtxt, TypeVisitableExt,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::ErrorGuaranteed;
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
use rustc_span::{ErrorGuaranteed, Symbol};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::BorrowckInferCtxt;
|
||||
|
@ -524,7 +524,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||
|
||||
let reg_vid = self
|
||||
.infcx
|
||||
.next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("c-variadic")))
|
||||
.next_nll_region_var(FR, || RegionCtxt::Free(sym::c_dash_variadic))
|
||||
.as_var();
|
||||
|
||||
let region = ty::Region::new_var(self.infcx.tcx, reg_vid);
|
||||
|
@ -540,10 +540,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let fr_fn_body = self
|
||||
.infcx
|
||||
.next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("fn_body")))
|
||||
.as_var();
|
||||
let fr_fn_body =
|
||||
self.infcx.next_nll_region_var(FR, || RegionCtxt::Free(sym::fn_body)).as_var();
|
||||
|
||||
let num_universals = self.infcx.num_region_vars();
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ fn create_jit_module(
|
|||
jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8);
|
||||
let mut jit_module = UnwindModule::new(JITModule::new(jit_builder), false);
|
||||
|
||||
let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, Symbol::intern("dummy_cgu_name"));
|
||||
let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name);
|
||||
|
||||
crate::allocator::codegen(tcx, &mut jit_module);
|
||||
|
||||
|
@ -276,12 +276,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
|
|||
|
||||
jit_module.module.prepare_for_function_redefine(func_id).unwrap();
|
||||
|
||||
let mut cx = crate::CodegenCx::new(
|
||||
tcx,
|
||||
jit_module.isa(),
|
||||
false,
|
||||
Symbol::intern("dummy_cgu_name"),
|
||||
);
|
||||
let mut cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name);
|
||||
codegen_and_compile_fn(tcx, &mut cx, &mut Context::new(), jit_module, instance);
|
||||
|
||||
assert!(cx.global_asm.is_empty());
|
||||
|
|
|
@ -189,18 +189,13 @@ impl CodegenBackend for CraneliftCodegenBackend {
|
|||
// FIXME return the actually used target features. this is necessary for #[cfg(target_feature)]
|
||||
if sess.target.arch == "x86_64" && sess.target.os != "none" {
|
||||
// x86_64 mandates SSE2 support
|
||||
vec![Symbol::intern("fxsr"), sym::sse, Symbol::intern("sse2")]
|
||||
vec![sym::fsxr, sym::sse, sym::sse2]
|
||||
} else if sess.target.arch == "aarch64" {
|
||||
match &*sess.target.os {
|
||||
"none" => vec![],
|
||||
// On macOS the aes, sha2 and sha3 features are enabled by default and ring
|
||||
// fails to compile on macOS when they are not present.
|
||||
"macos" => vec![
|
||||
sym::neon,
|
||||
Symbol::intern("aes"),
|
||||
Symbol::intern("sha2"),
|
||||
Symbol::intern("sha3"),
|
||||
],
|
||||
"macos" => vec![sym::neon, sym::aes, sym::sha2, sym::sha3],
|
||||
// AArch64 mandates Neon support
|
||||
_ => vec![sym::neon],
|
||||
}
|
||||
|
|
|
@ -419,7 +419,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
|||
if let Node::ConstBlock(_) = node {
|
||||
own_params.push(ty::GenericParamDef {
|
||||
index: next_index(),
|
||||
name: Symbol::intern("<const_ty>"),
|
||||
name: rustc_span::sym::const_ty_placeholder,
|
||||
def_id: def_id.to_def_id(),
|
||||
pure_wrt_drop: false,
|
||||
kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
|
||||
|
|
|
@ -664,7 +664,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.is_some_and(|def_id| {
|
||||
tcx.is_diagnostic_item(sym::write_macro, def_id)
|
||||
|| tcx.is_diagnostic_item(sym::writeln_macro, def_id)
|
||||
}) && item_name.name == Symbol::intern("write_fmt");
|
||||
}) && item_name.name == sym::write_fmt;
|
||||
let mut err = if is_write && let SelfSource::MethodCall(rcvr_expr) = source {
|
||||
self.suggest_missing_writer(rcvr_ty, rcvr_expr)
|
||||
} else {
|
||||
|
|
|
@ -775,6 +775,9 @@ lint_suspicious_double_ref_clone =
|
|||
lint_suspicious_double_ref_deref =
|
||||
using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type
|
||||
|
||||
lint_symbol_intern_string_literal = using `Symbol::intern` on a string literal
|
||||
.help = consider adding the symbol to `compiler/rustc_span/src/symbol.rs`
|
||||
|
||||
lint_trailing_semi_macro = trailing semicolon in macro used in expression position
|
||||
.note1 = macro invocations at the end of a block are treated as expressions
|
||||
.note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}`
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
@ -650,3 +651,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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -1563,7 +1563,7 @@ impl UnusedImportBraces {
|
|||
}
|
||||
rename.unwrap_or(orig_ident).name
|
||||
}
|
||||
ast::UseTreeKind::Glob => Symbol::intern("*"),
|
||||
ast::UseTreeKind::Glob => sym::asterisk,
|
||||
ast::UseTreeKind::Nested { .. } => return,
|
||||
};
|
||||
|
||||
|
|
|
@ -861,8 +861,10 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
// First up we check for global allocators. Look at the crate graph here
|
||||
// and see what's a global allocator, including if we ourselves are a
|
||||
// global allocator.
|
||||
let mut global_allocator =
|
||||
self.cstore.has_global_allocator.then(|| Symbol::intern("this crate"));
|
||||
#[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
|
||||
let this_crate = Symbol::intern("this crate");
|
||||
|
||||
let mut global_allocator = self.cstore.has_global_allocator.then_some(this_crate);
|
||||
for (_, data) in self.cstore.iter_crate_data() {
|
||||
if data.has_global_allocator() {
|
||||
match global_allocator {
|
||||
|
@ -876,8 +878,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
let mut alloc_error_handler =
|
||||
self.cstore.has_alloc_error_handler.then(|| Symbol::intern("this crate"));
|
||||
let mut alloc_error_handler = self.cstore.has_alloc_error_handler.then_some(this_crate);
|
||||
for (_, data) in self.cstore.iter_crate_data() {
|
||||
if data.has_alloc_error_handler() {
|
||||
match alloc_error_handler {
|
||||
|
|
|
@ -872,6 +872,7 @@ impl MetadataBlob {
|
|||
|
||||
let def_kind = root.tables.def_kind.get(blob, item).unwrap();
|
||||
let def_key = root.tables.def_keys.get(blob, item).unwrap().decode(blob);
|
||||
#[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
|
||||
let def_name = if item == CRATE_DEF_INDEX {
|
||||
rustc_span::symbol::kw::Crate
|
||||
} else {
|
||||
|
|
|
@ -9,7 +9,7 @@ use rustc_ast::{
|
|||
};
|
||||
use rustc_errors::{Applicability, PResult};
|
||||
use rustc_span::symbol::{Ident, kw, sym};
|
||||
use rustc_span::{ErrorGuaranteed, Span, Symbol};
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
||||
use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
|
||||
|
@ -1136,7 +1136,7 @@ impl<'a> Parser<'a> {
|
|||
Some(ast::Path {
|
||||
span: fn_token_span.to(self.prev_token.span),
|
||||
segments: thin_vec![ast::PathSegment {
|
||||
ident: Ident::new(Symbol::intern("Fn"), fn_token_span),
|
||||
ident: Ident::new(sym::Fn, fn_token_span),
|
||||
id: DUMMY_NODE_ID,
|
||||
args: Some(P(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs {
|
||||
span: args_lo.to(self.prev_token.span),
|
||||
|
|
|
@ -3113,6 +3113,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))]
|
||||
let existing_name = match &in_scope_lifetimes[..] {
|
||||
[] => Symbol::intern("'a"),
|
||||
[(existing, _)] => existing.name,
|
||||
|
|
|
@ -2257,7 +2257,7 @@ fn module_to_string(module: Module<'_>) -> Option<String> {
|
|||
collect_mod(names, parent);
|
||||
}
|
||||
} else {
|
||||
names.push(Symbol::intern("<opaque>"));
|
||||
names.push(sym::opaque_module_name_placeholder);
|
||||
collect_mod(names, module.parent.unwrap());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute]) -> Symbol {
|
|||
}
|
||||
}
|
||||
|
||||
Symbol::intern("rust_out")
|
||||
sym::rust_out
|
||||
}
|
||||
|
||||
pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option<Span>) {
|
||||
|
|
|
@ -298,6 +298,7 @@ symbols! {
|
|||
Return,
|
||||
Right,
|
||||
Rust,
|
||||
RustaceansAreAwesome,
|
||||
RustcDecodable,
|
||||
RustcEncodable,
|
||||
RwLock,
|
||||
|
@ -316,6 +317,7 @@ symbols! {
|
|||
StructuralPartialEq,
|
||||
SubdiagMessage,
|
||||
Subdiagnostic,
|
||||
SymbolIntern,
|
||||
Sync,
|
||||
SyncUnsafeCell,
|
||||
T,
|
||||
|
@ -377,6 +379,7 @@ symbols! {
|
|||
adt_const_params,
|
||||
advanced_slice_patterns,
|
||||
adx_target_feature,
|
||||
aes,
|
||||
aggregate_raw_ptr,
|
||||
alias,
|
||||
align,
|
||||
|
@ -440,6 +443,7 @@ symbols! {
|
|||
associated_types,
|
||||
assume,
|
||||
assume_init,
|
||||
asterisk: "*",
|
||||
async_await,
|
||||
async_call,
|
||||
async_call_mut,
|
||||
|
@ -521,6 +525,7 @@ symbols! {
|
|||
btreeset_iter,
|
||||
builtin_syntax,
|
||||
c,
|
||||
c_dash_variadic,
|
||||
c_str,
|
||||
c_str_literals,
|
||||
c_unwind,
|
||||
|
@ -651,6 +656,7 @@ symbols! {
|
|||
const_trait_bound_opt_out,
|
||||
const_trait_impl,
|
||||
const_try,
|
||||
const_ty_placeholder: "<const_ty>",
|
||||
constant,
|
||||
constructor,
|
||||
convert_identity,
|
||||
|
@ -780,6 +786,7 @@ symbols! {
|
|||
drop_types_in_const,
|
||||
dropck_eyepatch,
|
||||
dropck_parametricity,
|
||||
dummy_cgu_name,
|
||||
dylib,
|
||||
dyn_compatible_for_dispatch,
|
||||
dyn_metadata,
|
||||
|
@ -923,6 +930,7 @@ symbols! {
|
|||
fmuladdf32,
|
||||
fmuladdf64,
|
||||
fn_align,
|
||||
fn_body,
|
||||
fn_delegation,
|
||||
fn_must_use,
|
||||
fn_mut,
|
||||
|
@ -963,6 +971,7 @@ symbols! {
|
|||
fs_create_dir,
|
||||
fsub_algebraic,
|
||||
fsub_fast,
|
||||
fsxr,
|
||||
full,
|
||||
fundamental,
|
||||
fused_iterator,
|
||||
|
@ -1386,6 +1395,7 @@ symbols! {
|
|||
on,
|
||||
on_unimplemented,
|
||||
opaque,
|
||||
opaque_module_name_placeholder: "<opaque>",
|
||||
open_options_new,
|
||||
ops,
|
||||
opt_out_copy,
|
||||
|
@ -1655,6 +1665,7 @@ symbols! {
|
|||
rust_eh_catch_typeinfo,
|
||||
rust_eh_personality,
|
||||
rust_logo,
|
||||
rust_out,
|
||||
rustc,
|
||||
rustc_abi,
|
||||
rustc_allocator,
|
||||
|
@ -1777,6 +1788,8 @@ symbols! {
|
|||
self_in_typedefs,
|
||||
self_struct_ctor,
|
||||
semitransparent,
|
||||
sha2,
|
||||
sha3,
|
||||
sha512_sm_x86,
|
||||
shadow_call_stack,
|
||||
shallow,
|
||||
|
@ -1891,6 +1904,7 @@ symbols! {
|
|||
sreg,
|
||||
sreg_low16,
|
||||
sse,
|
||||
sse2,
|
||||
sse4a_target_feature,
|
||||
stable,
|
||||
staged_api,
|
||||
|
@ -2178,6 +2192,7 @@ symbols! {
|
|||
wrapping_sub,
|
||||
wreg,
|
||||
write_bytes,
|
||||
write_fmt,
|
||||
write_macro,
|
||||
write_str,
|
||||
write_via_move,
|
||||
|
@ -2407,6 +2422,7 @@ impl Symbol {
|
|||
}
|
||||
|
||||
/// Maps a string to its interned representation.
|
||||
#[rustc_diagnostic_item = "SymbolIntern"]
|
||||
pub fn intern(string: &str) -> Self {
|
||||
with_session_globals(|session_globals| session_globals.symbol_interner.intern(string))
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ use rustc_middle::ty::{
|
|||
TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
|
||||
};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use smallvec::SmallVec;
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
|
@ -679,7 +678,7 @@ fn receiver_is_dispatchable<'tcx>(
|
|||
// FIXME(mikeyhew) this is a total hack. Once dyn_compatible_for_dispatch is stabilized, we can
|
||||
// replace this with `dyn Trait`
|
||||
let unsized_self_ty: Ty<'tcx> =
|
||||
Ty::new_param(tcx, u32::MAX, Symbol::intern("RustaceansAreAwesome"));
|
||||
Ty::new_param(tcx, u32::MAX, rustc_span::sym::RustaceansAreAwesome);
|
||||
|
||||
// `Receiver[Self => U]`
|
||||
let unsized_receiver_ty =
|
||||
|
|
|
@ -1033,6 +1033,15 @@ impl Builder<'_> {
|
|||
|
||||
if mode == Mode::Rustc {
|
||||
rustflags.arg("-Wrustc::internal");
|
||||
// cfg(bootstrap) - remove this check when lint is in bootstrap compiler
|
||||
if stage != 0 {
|
||||
// Lint is allow by default so downstream tools don't get a lit
|
||||
// they can do nothing about
|
||||
// We shouldn't be preinterning symbols used by tests
|
||||
if cmd_kind != Kind::Test {
|
||||
rustflags.arg("-Drustc::symbol_intern_string_literal");
|
||||
}
|
||||
}
|
||||
// FIXME(edition_2024): Change this to `-Wrust_2024_idioms` when all
|
||||
// of the individual lints are satisfied.
|
||||
rustflags.arg("-Wkeyword_idents_2024");
|
||||
|
|
Loading…
Add table
Reference in a new issue