Skip to content

Commit 7f9f26b

Browse files
committed
Port crate name to the new attribute system
1 parent 020b268 commit 7f9f26b

25 files changed

+248
-156
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use super::prelude::*;
2+
3+
pub(crate) struct CrateNameParser;
4+
5+
impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
6+
const PATH: &[Symbol] = &[sym::crate_name];
7+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
8+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
9+
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
10+
11+
// FIXME: crate name is allowed on all targets and ignored,
12+
// even though it should only be valid on crates of course
13+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
14+
15+
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
16+
let ArgParser::NameValue(n) = args else {
17+
cx.expected_name_value(cx.attr_span, None);
18+
return None;
19+
};
20+
21+
let Some(name) = n.value_as_str() else {
22+
cx.expected_string_literal(n.value_span, Some(n.value_as_lit()));
23+
return None;
24+
};
25+
26+
Some(AttributeKind::CrateName {
27+
name,
28+
name_span: n.value_span,
29+
attr_span: cx.attr_span,
30+
style: cx.attr_style,
31+
})
32+
}
33+
}

compiler/rustc_attr_parsing/src/attributes/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub(crate) mod cfg;
3535
pub(crate) mod cfg_old;
3636
pub(crate) mod codegen_attrs;
3737
pub(crate) mod confusables;
38+
pub(crate) mod crate_level;
3839
pub(crate) mod deprecation;
3940
pub(crate) mod dummy;
4041
pub(crate) mod inline;

compiler/rustc_attr_parsing/src/attributes/util.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use rustc_ast::LitKind;
2-
use rustc_ast::attr::{AttributeExt, first_attr_value_str_by_name};
2+
use rustc_ast::attr::AttributeExt;
33
use rustc_feature::is_builtin_attr_name;
44
use rustc_hir::RustcVersion;
55
use rustc_span::{Symbol, sym};
@@ -27,10 +27,6 @@ pub fn is_builtin_attr(attr: &impl AttributeExt) -> bool {
2727
attr.is_doc_comment() || attr.ident().is_some_and(|ident| is_builtin_attr_name(ident.name))
2828
}
2929

30-
pub fn find_crate_name(attrs: &[impl AttributeExt]) -> Option<Symbol> {
31-
first_attr_value_str_by_name(attrs, sym::crate_name)
32-
}
33-
3430
pub fn is_doc_alias_attrs_contain_symbol<'tcx, T: AttributeExt + 'tcx>(
3531
attrs: impl Iterator<Item = &'tcx T>,
3632
symbol: Symbol,

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::attributes::codegen_attrs::{
2323
NoMangleParser, OptimizeParser, TargetFeatureParser, TrackCallerParser, UsedParser,
2424
};
2525
use crate::attributes::confusables::ConfusablesParser;
26+
use crate::attributes::crate_level::CrateNameParser;
2627
use crate::attributes::deprecation::DeprecationParser;
2728
use crate::attributes::dummy::DummyParser;
2829
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
@@ -165,6 +166,7 @@ attribute_parsers!(
165166

166167
// tidy-alphabetical-start
167168
Single<CoverageParser>,
169+
Single<CrateNameParser>,
168170
Single<CustomMirParser>,
169171
Single<DeprecationParser>,
170172
Single<DummyParser>,
@@ -308,7 +310,9 @@ pub struct AcceptContext<'f, 'sess, S: Stage> {
308310
/// The span of the attribute currently being parsed
309311
pub(crate) attr_span: Span,
310312

313+
/// Whether it is an inner or outer attribute
311314
pub(crate) attr_style: AttrStyle,
315+
312316
/// The expected structure of the attribute.
313317
///
314318
/// Used in reporting errors to give a hint to users what the attribute *should* look like.
@@ -681,7 +685,9 @@ impl ShouldEmit {
681685
ShouldEmit::ErrorsAndLints => {
682686
diag.emit();
683687
}
684-
ShouldEmit::Nothing => {}
688+
ShouldEmit::Nothing => {
689+
diag.cancel();
690+
}
685691
}
686692
}
687693
}

compiler/rustc_attr_parsing/src/lib.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,7 @@ pub mod validate_attr;
106106

107107
pub use attributes::cfg::{CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg_attr};
108108
pub use attributes::cfg_old::*;
109-
pub use attributes::util::{
110-
find_crate_name, is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version,
111-
};
109+
pub use attributes::util::{is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version};
112110
pub use context::{Early, Late, OmitDoc, ShouldEmit};
113111
pub use interface::AttributeParser;
114112
pub use lints::emit_attribute_lint;

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,9 @@ pub enum AttributeKind {
366366
/// Represents `#[coverage(..)]`.
367367
Coverage(Span, CoverageAttrKind),
368368

369+
/// Represents `#[crate_name = ...]`
370+
CrateName { name: Symbol, name_span: Span, attr_span: Span, style: AttrStyle },
371+
369372
/// Represents `#[custom_mir]`.
370373
CustomMir(Option<(MirDialect, Span)>, Option<(MirPhase, Span)>, Span),
371374

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ pub enum EncodeCrossCrate {
77
}
88

99
impl AttributeKind {
10+
/// Whether this attribute should be encoded in metadata files.
11+
///
12+
/// If this is "Yes", then another crate can do `tcx.get_all_attrs(did)` for a did in this crate, and get the attribute.
13+
/// When this is No, the attribute is filtered out while encoding and other crate won't be able to observe it.
14+
/// This can be unexpectedly good for performance, so unless necessary for cross-crate compilation, prefer No.
1015
pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
1116
use AttributeKind::*;
1217
use EncodeCrossCrate::*;
@@ -31,6 +36,7 @@ impl AttributeKind {
3136
ConstTrait(..) => No,
3237
Coroutine(..) => No,
3338
Coverage(..) => No,
39+
CrateName { .. } => No,
3440
CustomMir(_, _, _) => Yes,
3541
DenyExplicitImpl(..) => No,
3642
Deprecation { .. } => Yes,

compiler/rustc_interface/src/passes.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::sync::{Arc, LazyLock, OnceLock};
66
use std::{env, fs, iter};
77

88
use rustc_ast as ast;
9-
use rustc_attr_parsing::validate_attr;
9+
use rustc_attr_parsing::{AttributeParser, ShouldEmit, validate_attr};
1010
use rustc_codegen_ssa::traits::CodegenBackend;
1111
use rustc_data_structures::jobserver::Proxy;
1212
use rustc_data_structures::steal::Steal;
@@ -16,6 +16,7 @@ use rustc_errors::timings::TimingSection;
1616
use rustc_expand::base::{ExtCtxt, LintStoreExpand};
1717
use rustc_feature::Features;
1818
use rustc_fs_util::try_canonicalize;
19+
use rustc_hir::attrs::AttributeKind;
1920
use rustc_hir::def_id::{LOCAL_CRATE, StableCrateId, StableCrateIdMap};
2021
use rustc_hir::definitions::Definitions;
2122
use rustc_incremental::setup_dep_graph;
@@ -1244,8 +1245,7 @@ pub fn get_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) -> Symbol
12441245
// in all code paths that require the crate name very early on, namely before
12451246
// macro expansion.
12461247

1247-
let attr_crate_name =
1248-
validate_and_find_value_str_builtin_attr(sym::crate_name, sess, krate_attrs);
1248+
let attr_crate_name = parse_crate_name(sess, krate_attrs, ShouldEmit::EarlyFatal);
12491249

12501250
let validate = |name, span| {
12511251
rustc_session::output::validate_crate_name(sess, name, span);
@@ -1283,6 +1283,28 @@ pub fn get_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) -> Symbol
12831283
sym::rust_out
12841284
}
12851285

1286+
pub(crate) fn parse_crate_name(
1287+
sess: &Session,
1288+
attrs: &[ast::Attribute],
1289+
emit_errors: ShouldEmit,
1290+
) -> Option<(Symbol, Span)> {
1291+
let rustc_hir::Attribute::Parsed(AttributeKind::CrateName { name, name_span, .. }) =
1292+
AttributeParser::parse_limited_should_emit(
1293+
sess,
1294+
&attrs,
1295+
sym::crate_name,
1296+
DUMMY_SP,
1297+
rustc_ast::node_id::CRATE_NODE_ID,
1298+
None,
1299+
emit_errors,
1300+
)?
1301+
else {
1302+
unreachable!("crate_name is the only attr we could've parsed here");
1303+
};
1304+
1305+
Some((name, name_span))
1306+
}
1307+
12861308
fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit {
12871309
// We don't permit macro calls inside of the attribute (e.g., #![recursion_limit = `expand!()`])
12881310
// because that would require expanding this while in the middle of expansion, which needs to

compiler/rustc_interface/src/util.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::sync::{Arc, OnceLock};
55
use std::{env, thread};
66

77
use rustc_ast as ast;
8-
use rustc_attr_parsing::validate_attr;
8+
use rustc_attr_parsing::{ShouldEmit, validate_attr};
99
use rustc_codegen_ssa::traits::CodegenBackend;
1010
use rustc_data_structures::jobserver::Proxy;
1111
use rustc_data_structures::sync;
@@ -24,6 +24,7 @@ use rustc_target::spec::Target;
2424
use tracing::info;
2525

2626
use crate::errors;
27+
use crate::passes::parse_crate_name;
2728

2829
/// Function pointer type that constructs a new CodegenBackend.
2930
type MakeBackendFn = fn() -> Box<dyn CodegenBackend>;
@@ -520,11 +521,10 @@ pub fn build_output_filenames(attrs: &[ast::Attribute], sess: &Session) -> Outpu
520521
sess.dcx().emit_fatal(errors::MultipleOutputTypesToStdout);
521522
}
522523

523-
let crate_name = sess
524-
.opts
525-
.crate_name
526-
.clone()
527-
.or_else(|| rustc_attr_parsing::find_crate_name(attrs).map(|n| n.to_string()));
524+
let crate_name =
525+
sess.opts.crate_name.clone().or_else(|| {
526+
parse_crate_name(sess, attrs, ShouldEmit::Nothing).map(|i| i.0.to_string())
527+
});
528528

529529
match sess.io.output_file {
530530
None => {

compiler/rustc_lint/src/nonstandard_style.rs

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_hir::attrs::{AttributeKind, ReprAttr};
55
use rustc_hir::def::{DefKind, Res};
66
use rustc_hir::def_id::DefId;
77
use rustc_hir::intravisit::{FnKind, Visitor};
8-
use rustc_hir::{AttrArgs, AttrItem, Attribute, GenericParamKind, PatExprKind, PatKind, find_attr};
8+
use rustc_hir::{Attribute, GenericParamKind, PatExprKind, PatKind, find_attr};
99
use rustc_middle::hir::nested_filter::All;
1010
use rustc_middle::ty;
1111
use rustc_session::config::CrateType;
@@ -343,35 +343,27 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
343343
let crate_ident = if let Some(name) = &cx.tcx.sess.opts.crate_name {
344344
Some(Ident::from_str(name))
345345
} else {
346-
ast::attr::find_by_name(cx.tcx.hir_attrs(hir::CRATE_HIR_ID), sym::crate_name).and_then(
347-
|attr| {
348-
if let Attribute::Unparsed(n) = attr
349-
&& let AttrItem { args: AttrArgs::Eq { eq_span: _, expr: lit }, .. } =
350-
n.as_ref()
351-
&& let ast::LitKind::Str(name, ..) = lit.kind
352-
{
353-
// Discard the double quotes surrounding the literal.
354-
let sp = cx
355-
.sess()
356-
.source_map()
357-
.span_to_snippet(lit.span)
358-
.ok()
359-
.and_then(|snippet| {
360-
let left = snippet.find('"')?;
361-
let right = snippet.rfind('"').map(|pos| snippet.len() - pos)?;
362-
363-
Some(
364-
lit.span
365-
.with_lo(lit.span.lo() + BytePos(left as u32 + 1))
366-
.with_hi(lit.span.hi() - BytePos(right as u32)),
367-
)
368-
})
369-
.unwrap_or(lit.span);
370-
371-
Some(Ident::new(name, sp))
372-
} else {
373-
None
374-
}
346+
find_attr!(cx.tcx.hir_attrs(hir::CRATE_HIR_ID), AttributeKind::CrateName{name, name_span,..} => (name, name_span)).map(
347+
|(&name, &span)| {
348+
// Discard the double quotes surrounding the literal.
349+
let sp = cx
350+
.sess()
351+
.source_map()
352+
.span_to_snippet(span)
353+
.ok()
354+
.and_then(|snippet| {
355+
let left = snippet.find('"')?;
356+
let right = snippet.rfind('"').map(|pos| snippet.len() - pos)?;
357+
358+
Some(
359+
span
360+
.with_lo(span.lo() + BytePos(left as u32 + 1))
361+
.with_hi(span.hi() - BytePos(right as u32)),
362+
)
363+
})
364+
.unwrap_or(span);
365+
366+
Ident::new(name, sp)
375367
},
376368
)
377369
};

0 commit comments

Comments
 (0)