Skip to content

Commit 86f64ca

Browse files
committed
Port crate name to the new attribute system
1 parent 68d388f commit 86f64ca

31 files changed

+378
-190
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use rustc_feature::{AttributeTemplate, template};
2+
use rustc_hir::attrs::AttributeKind;
3+
use rustc_span::{Symbol, sym};
4+
5+
use super::{AttributeOrder, OnDuplicate, SingleAttributeParser};
6+
use crate::context::{AcceptContext, Stage};
7+
use crate::parser::ArgParser;
8+
9+
pub(crate) struct CrateNameParser;
10+
11+
impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
12+
const PATH: &[Symbol] = &[sym::crate_name];
13+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
14+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
15+
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
16+
17+
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
18+
let ArgParser::NameValue(n) = args else {
19+
cx.expected_name_value(cx.attr_span, None);
20+
return None;
21+
};
22+
23+
let Some(name) = n.value_as_str() else {
24+
cx.expected_string_literal(n.value_span, Some(n.value_as_lit()));
25+
return None;
26+
};
27+
28+
Some(AttributeKind::CrateName { name, name_span: n.value_span, style: cx.attr_style })
29+
}
30+
}

compiler/rustc_attr_parsing/src/attributes/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub(crate) mod cfg;
3131
pub(crate) mod cfg_old;
3232
pub(crate) mod codegen_attrs;
3333
pub(crate) mod confusables;
34+
pub(crate) mod crate_level;
3435
pub(crate) mod deprecation;
3536
pub(crate) mod dummy;
3637
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,4 +1,4 @@
1-
use rustc_ast::attr::{AttributeExt, first_attr_value_str_by_name};
1+
use rustc_ast::attr::AttributeExt;
22
use rustc_feature::is_builtin_attr_name;
33
use rustc_hir::RustcVersion;
44
use rustc_span::{Symbol, sym};
@@ -23,10 +23,6 @@ pub fn is_builtin_attr(attr: &impl AttributeExt) -> bool {
2323
attr.is_doc_comment() || attr.ident().is_some_and(|ident| is_builtin_attr_name(ident.name))
2424
}
2525

26-
pub fn find_crate_name(attrs: &[impl AttributeExt]) -> Option<Symbol> {
27-
first_attr_value_str_by_name(attrs, sym::crate_name)
28-
}
29-
3026
pub fn is_doc_alias_attrs_contain_symbol<'tcx, T: AttributeExt + 'tcx>(
3127
attrs: impl Iterator<Item = &'tcx T>,
3228
symbol: Symbol,

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use rustc_hir::attrs::AttributeKind;
1111
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
1212
use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, HirId};
1313
use rustc_session::Session;
14+
use rustc_session::lint::BuiltinLintDiag;
1415
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
1516

1617
use crate::attributes::allow_unstable::{
@@ -22,6 +23,7 @@ use crate::attributes::codegen_attrs::{
2223
TargetFeatureParser, TrackCallerParser, UsedParser,
2324
};
2425
use crate::attributes::confusables::ConfusablesParser;
26+
use crate::attributes::crate_level::CrateNameParser;
2527
use crate::attributes::deprecation::DeprecationParser;
2628
use crate::attributes::dummy::DummyParser;
2729
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
@@ -59,6 +61,7 @@ use crate::attributes::traits::{
5961
};
6062
use crate::attributes::transparency::TransparencyParser;
6163
use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
64+
use crate::lints::lint_name;
6265
use crate::parser::{ArgParser, MetaItemParser, PathParser};
6366
use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem};
6467

@@ -157,6 +160,7 @@ attribute_parsers!(
157160

158161
// tidy-alphabetical-start
159162
Single<CoverageParser>,
163+
Single<CrateNameParser>,
160164
Single<DeprecationParser>,
161165
Single<DummyParser>,
162166
Single<ExportNameParser>,
@@ -301,7 +305,9 @@ pub struct AcceptContext<'f, 'sess, S: Stage> {
301305
/// The span of the attribute currently being parsed
302306
pub(crate) attr_span: Span,
303307

308+
/// Whether it is an inner or outer attribute
304309
pub(crate) attr_style: AttrStyle,
310+
305311
/// The expected structure of the attribute.
306312
///
307313
/// Used in reporting errors to give a hint to users what the attribute *should* look like.
@@ -689,22 +695,48 @@ impl<'sess> AttributeParser<'sess, Early> {
689695
target_span: Span,
690696
target_node_id: NodeId,
691697
features: Option<&'sess Features>,
698+
) -> Option<Attribute> {
699+
Self::parse_limited_should_emit(
700+
sess,
701+
attrs,
702+
sym,
703+
target_span,
704+
target_node_id,
705+
features,
706+
ShouldEmit::Nothing,
707+
)
708+
}
709+
710+
/// Usually you want `parse_limited`, which defaults to no errors.
711+
pub fn parse_limited_should_emit(
712+
sess: &'sess Session,
713+
attrs: &[ast::Attribute],
714+
sym: Symbol,
715+
target_span: Span,
716+
target_node_id: NodeId,
717+
features: Option<&'sess Features>,
718+
should_emit: ShouldEmit,
692719
) -> Option<Attribute> {
693720
let mut p = Self {
694721
features,
695722
tools: Vec::new(),
696723
parse_only: Some(sym),
697724
sess,
698-
stage: Early { emit_errors: ShouldEmit::Nothing },
725+
stage: Early { emit_errors: should_emit },
699726
};
700727
let mut parsed = p.parse_attribute_list(
701728
attrs,
702729
target_span,
703730
target_node_id,
704731
OmitDoc::Skip,
705732
std::convert::identity,
706-
|_lint| {
707-
panic!("can't emit lints here for now (nothing uses this atm)");
733+
|AttributeLint { id, span, kind }| {
734+
sess.psess.buffer_lint(
735+
lint_name(&kind),
736+
span,
737+
id,
738+
BuiltinLintDiag::AttributeLint(kind),
739+
);
708740
},
709741
);
710742
assert!(parsed.len() <= 1);

compiler/rustc_attr_parsing/src/lib.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,8 @@ mod session_diagnostics;
9292

9393
pub use attributes::cfg::{CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg_attr};
9494
pub use attributes::cfg_old::*;
95-
pub use attributes::util::{
96-
find_crate_name, is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version,
97-
};
95+
pub use attributes::util::{is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version};
9896
pub use context::{AttributeParser, Early, Late, OmitDoc, ShouldEmit};
99-
pub use lints::emit_attribute_lint;
97+
pub use lints::{decorate_attribute_lint_kind, emit_attribute_lint};
10098

10199
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,48 @@
1-
use rustc_errors::{DiagArgValue, LintEmitter};
1+
use rustc_errors::{AttributeLintDecorator, DeferedAttributeLintDecorator, DiagArgValue};
22
use rustc_hir::HirId;
33
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
4+
use rustc_session::lint::Lint;
45

56
use crate::session_diagnostics;
67

7-
pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emitter: L) {
8-
let AttributeLint { id, span, kind } = lint;
8+
pub(crate) fn lint_name(kind: &AttributeLintKind) -> &'static Lint {
9+
use rustc_session::lint::builtin::*;
10+
match kind {
11+
AttributeLintKind::UnusedDuplicate { .. } => UNUSED_ATTRIBUTES,
12+
AttributeLintKind::IllFormedAttributeInput { .. } => ILL_FORMED_ATTRIBUTE_INPUT,
13+
AttributeLintKind::EmptyAttribute { .. } => UNUSED_ATTRIBUTES,
14+
}
15+
}
916

17+
pub fn decorate_attribute_lint_kind<L: AttributeLintDecorator>(
18+
kind: &AttributeLintKind,
19+
lint_emitter: L,
20+
) {
1021
match kind {
11-
&AttributeLintKind::UnusedDuplicate { this, other, warning } => lint_emitter
12-
.emit_node_span_lint(
13-
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
14-
*id,
15-
*span,
16-
session_diagnostics::UnusedDuplicate { this, other, warning },
17-
),
22+
&AttributeLintKind::UnusedDuplicate { this, other, warning } => {
23+
lint_emitter.decorate(session_diagnostics::UnusedDuplicate { this, other, warning })
24+
}
1825
AttributeLintKind::IllFormedAttributeInput { suggestions } => {
19-
lint_emitter.emit_node_span_lint(
20-
rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT,
21-
*id,
22-
*span,
23-
session_diagnostics::IllFormedAttributeInput {
24-
num_suggestions: suggestions.len(),
25-
suggestions: DiagArgValue::StrListSepByAnd(
26-
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
27-
),
28-
},
29-
);
26+
lint_emitter.decorate(session_diagnostics::IllFormedAttributeInput {
27+
num_suggestions: suggestions.len(),
28+
suggestions: DiagArgValue::StrListSepByAnd(
29+
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
30+
),
31+
});
3032
}
31-
AttributeLintKind::EmptyAttribute { first_span } => lint_emitter.emit_node_span_lint(
32-
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
33-
*id,
34-
*first_span,
35-
session_diagnostics::EmptyAttributeList { attr_span: *first_span },
36-
),
33+
AttributeLintKind::EmptyAttribute { first_span } => lint_emitter
34+
.decorate(session_diagnostics::EmptyAttributeList { attr_span: *first_span }),
3735
}
3836
}
37+
38+
pub fn emit_attribute_lint<L: DeferedAttributeLintDecorator<ID = HirId>>(
39+
lint: &AttributeLint<HirId>,
40+
lint_emitter: L,
41+
) {
42+
let AttributeLint { id, span, kind } = lint;
43+
44+
let lint_name = lint_name(&lint.kind);
45+
46+
let emit = lint_emitter.prepare(lint_name, *id, *span);
47+
decorate_attribute_lint_kind(kind, emit);
48+
}

compiler/rustc_errors/src/lib.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ pub use rustc_error_messages::{
6060
SubdiagMessage, fallback_fluent_bundle, fluent_bundle,
6161
};
6262
use rustc_hashes::Hash128;
63-
use rustc_hir::HirId;
6463
pub use rustc_lint_defs::{Applicability, listify, pluralize};
6564
use rustc_lint_defs::{Lint, LintExpectationId};
6665
use rustc_macros::{Decodable, Encodable};
@@ -105,17 +104,23 @@ rustc_data_structures::static_assert_size!(PResult<'_, ()>, 24);
105104
#[cfg(target_pointer_width = "64")]
106105
rustc_data_structures::static_assert_size!(PResult<'_, bool>, 24);
107106

107+
pub trait AttributeLintDecorator {
108+
fn decorate(self, diag: impl for<'a> LintDiagnostic<'a, ()>);
109+
}
110+
108111
/// Used to avoid depending on `rustc_middle` in `rustc_attr_parsing`.
109112
/// Always the `TyCtxt`.
110-
pub trait LintEmitter: Copy {
113+
pub trait DeferedAttributeLintDecorator: Copy {
114+
type ID: Copy;
115+
type Decorator: AttributeLintDecorator;
116+
111117
#[track_caller]
112-
fn emit_node_span_lint(
118+
fn prepare(
113119
self,
114120
lint: &'static Lint,
115-
hir_id: HirId,
121+
id: Self::ID,
116122
span: impl Into<MultiSpan>,
117-
decorator: impl for<'a> LintDiagnostic<'a, ()>,
118-
);
123+
) -> Self::Decorator;
119124
}
120125

121126
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Encodable, Decodable)]

compiler/rustc_hir/src/attrs/data_structures.rs

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

306+
/// Represents `#[crate_name = ...]`
307+
CrateName { name: Symbol, name_span: Span, style: AttrStyle },
308+
306309
///Represents `#[rustc_deny_explicit_impl]`.
307310
DenyExplicitImpl(Span),
308311

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::*;
@@ -30,6 +35,7 @@ impl AttributeKind {
3035
ConstTrait(..) => No,
3136
Coroutine(..) => No,
3237
Coverage(..) => No,
38+
CrateName { .. } => No,
3339
DenyExplicitImpl(..) => No,
3440
Deprecation { .. } => Yes,
3541
DoNotImplementViaObject(..) => No,

compiler/rustc_interface/src/passes.rs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use std::path::{Path, PathBuf};
55
use std::sync::{Arc, LazyLock, OnceLock};
66
use std::{env, fs, iter};
77

8-
use rustc_ast as ast;
8+
use rustc_ast::{self as ast};
9+
use rustc_attr_parsing::{AttributeParser, ShouldEmit};
910
use rustc_codegen_ssa::traits::CodegenBackend;
1011
use rustc_data_structures::jobserver::Proxy;
1112
use rustc_data_structures::steal::Steal;
@@ -15,6 +16,7 @@ use rustc_errors::timings::TimingSection;
1516
use rustc_expand::base::{ExtCtxt, LintStoreExpand};
1617
use rustc_feature::Features;
1718
use rustc_fs_util::try_canonicalize;
19+
use rustc_hir::attrs::AttributeKind;
1820
use rustc_hir::def_id::{LOCAL_CRATE, StableCrateId, StableCrateIdMap};
1921
use rustc_hir::definitions::Definitions;
2022
use rustc_incremental::setup_dep_graph;
@@ -1244,8 +1246,7 @@ pub fn get_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) -> Symbol
12441246
// in all code paths that require the crate name very early on, namely before
12451247
// macro expansion.
12461248

1247-
let attr_crate_name =
1248-
validate_and_find_value_str_builtin_attr(sym::crate_name, sess, krate_attrs);
1249+
let attr_crate_name = parse_crate_name(sess, krate_attrs, ShouldEmit::ErrorsAndLints);
12491250

12501251
let validate = |name, span| {
12511252
rustc_session::output::validate_crate_name(sess, name, span);
@@ -1283,6 +1284,28 @@ pub fn get_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) -> Symbol
12831284
sym::rust_out
12841285
}
12851286

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

0 commit comments

Comments
 (0)