Skip to content

Commit 4a1be4b

Browse files
committed
refactor: more general terminology and use existing attr parse machinery
1 parent e8173a7 commit 4a1be4b

11 files changed

Lines changed: 158 additions & 121 deletions

File tree

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ struct LoweringContext<'a, 'hir, R> {
155155

156156
impl<'a, 'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'a, 'hir, R> {
157157
fn new(tcx: TyCtxt<'hir>, resolver: &'a mut R) -> Self {
158-
let registered_tools = tcx.registered_tools(()).iter().map(|x| x.name).collect();
158+
let registered_tools = tcx.registered_tools(());
159159
let attr_res_map = resolver.all_attr_resolutions();
160160
Self {
161161
tcx,

compiler/rustc_attr_parsing/src/attributes/repr.rs

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use rustc_abi::{Align, Size};
22
use rustc_ast::{IntTy, LitIntType, LitKind, UintTy};
3-
use rustc_hir::attrs::{AttrConstResolved, AttrIntValue, IntType, ReprAttr};
3+
use rustc_hir::attrs::{AttrIntValue, AttrResolutionKind, AttrResolved, IntType, ReprAttr};
44
use rustc_hir::def::{DefKind, Res};
55
use rustc_session::parse::feature_err;
66

@@ -105,7 +105,10 @@ fn int_type_of_word(s: Symbol) -> Option<IntType> {
105105
}
106106
}
107107

108-
fn parse_repr<S: Stage>(cx: &AcceptContext<'_, '_, S>, param: &MetaItemParser) -> Option<ReprAttr> {
108+
fn parse_repr<S: Stage>(
109+
cx: &mut AcceptContext<'_, '_, S>,
110+
param: &MetaItemParser,
111+
) -> Option<ReprAttr> {
109112
use ReprAttr::*;
110113

111114
// FIXME(jdonszelmann): invert the parsing here to match on the word first and then the
@@ -200,7 +203,7 @@ enum AlignmentParseError {
200203
}
201204

202205
fn parse_repr_align<S: Stage>(
203-
cx: &AcceptContext<'_, '_, S>,
206+
cx: &mut AcceptContext<'_, '_, S>,
204207
list: &MetaItemListParser,
205208
param_span: Span,
206209
align_kind: AlignKind,
@@ -283,7 +286,7 @@ fn parse_alignment<S: Stage>(
283286
}
284287

285288
fn parse_alignment_or_const_path<S: Stage>(
286-
cx: &AcceptContext<'_, '_, S>,
289+
cx: &mut AcceptContext<'_, '_, S>,
287290
arg: &MetaItemOrLitParser,
288291
attr_name: &'static str,
289292
) -> Result<AttrIntValue, AlignmentParseError> {
@@ -301,10 +304,15 @@ fn parse_alignment_or_const_path<S: Stage>(
301304
return Err(AlignmentParseError::Message("not an unsuffixed integer".to_string()));
302305
}
303306

304-
if let Some(features) = cx.features_option()
305-
&& !features.const_attr_paths()
306-
&& !meta.span().allows_unstable(sym::const_attr_paths)
307-
{
307+
let path_span = meta.path().span();
308+
let feature_enabled = cx.features_option().is_some_and(|features| features.const_attr_paths())
309+
|| path_span.allows_unstable(sym::const_attr_paths);
310+
311+
if !feature_enabled {
312+
if matches!(cx.stage.should_emit(), ShouldEmit::Nothing) {
313+
return Ok(AttrIntValue::Lit(1));
314+
}
315+
308316
feature_err(
309317
cx.sess(),
310318
sym::const_attr_paths,
@@ -315,7 +323,9 @@ fn parse_alignment_or_const_path<S: Stage>(
315323
return Err(AlignmentParseError::AlreadyErrored);
316324
}
317325

318-
let Some(resolution) = cx.attr_const_resolution(meta.path().span()) else {
326+
cx.record_attr_resolution_request(AttrResolutionKind::Const, meta.path().0.clone());
327+
328+
let Some(resolution) = cx.attr_resolution(AttrResolutionKind::Const, path_span) else {
319329
// `parse_limited(sym::repr)` runs before lowering for callers that only care whether
320330
// `repr(packed(...))` exists at all.
321331
if matches!(cx.stage.should_emit(), ShouldEmit::Nothing) {
@@ -325,22 +335,18 @@ fn parse_alignment_or_const_path<S: Stage>(
325335
};
326336

327337
match resolution {
328-
AttrConstResolved::Resolved(Res::Def(DefKind::Const { .. }, def_id)) => {
329-
Ok(AttrIntValue::Const { def_id, span: meta.path().span() })
338+
AttrResolved::Resolved(Res::Def(DefKind::Const { .. }, def_id)) => {
339+
Ok(AttrIntValue::Const { def_id, span: path_span })
330340
}
331-
AttrConstResolved::Resolved(Res::Def(DefKind::ConstParam, _)) => {
332-
cx.emit_err(AttrConstGenericNotSupported { span: meta.path().span(), attr_name });
341+
AttrResolved::Resolved(Res::Def(DefKind::ConstParam, _)) => {
342+
cx.emit_err(AttrConstGenericNotSupported { span: path_span, attr_name });
333343
Err(AlignmentParseError::AlreadyErrored)
334344
}
335-
AttrConstResolved::Resolved(res) => {
336-
cx.emit_err(AttrConstPathNotConst {
337-
span: meta.path().span(),
338-
attr_name,
339-
thing: res.descr(),
340-
});
345+
AttrResolved::Resolved(res) => {
346+
cx.emit_err(AttrConstPathNotConst { span: path_span, attr_name, thing: res.descr() });
341347
Err(AlignmentParseError::AlreadyErrored)
342348
}
343-
AttrConstResolved::Error => Err(AlignmentParseError::AlreadyErrored),
349+
AttrResolved::Error => Err(AlignmentParseError::AlreadyErrored),
344350
}
345351
}
346352

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use private::Sealed;
99
use rustc_ast::{AttrStyle, MetaItemLit, NodeId};
1010
use rustc_errors::{Diag, Diagnostic, Level};
1111
use rustc_feature::{AttrSuggestionStyle, AttributeTemplate};
12-
use rustc_hir::attrs::AttributeKind;
12+
use rustc_hir::attrs::{AttrResolutionKind, AttributeKind};
1313
use rustc_hir::lints::AttributeLintKind;
1414
use rustc_hir::{AttrPath, HirId};
1515
use rustc_parse::parser::Recovery;
@@ -416,7 +416,6 @@ pub struct Late;
416416
/// Gives [`AttributeParser`]s enough information to create errors, for example.
417417
pub struct AcceptContext<'f, 'sess, S: Stage> {
418418
pub(crate) shared: SharedContext<'f, 'sess, S>,
419-
pub(crate) attr_id: Option<AttrId>,
420419

421420
/// The outer span of the attribute currently being parsed
422421
///
@@ -502,13 +501,25 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
502501
impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
503502
pub(crate) fn adcx(&mut self) -> AttributeDiagnosticContext<'_, 'f, 'sess, S> {
504503
AttributeDiagnosticContext { ctx: self, custom_suggestions: Vec::new() }
504+
}
505505

506-
pub(crate) fn attr_const_resolution(
506+
pub(crate) fn attr_resolution(
507507
&self,
508+
kind: AttrResolutionKind,
508509
path_span: Span,
509-
) -> Option<rustc_hir::attrs::AttrConstResolved<NodeId>> {
510-
self.attr_id.and_then(|attr_id| self.shared.cx.attr_const_resolution(attr_id, path_span))
510+
) -> Option<rustc_hir::attrs::AttrResolved<NodeId>> {
511+
self.shared.cx.attr_resolution(self.attr_id, kind, path_span)
511512
}
513+
514+
pub(crate) fn record_attr_resolution_request(
515+
&mut self,
516+
kind: AttrResolutionKind,
517+
path: rustc_ast::Path,
518+
) {
519+
self.shared.cx.record_attr_resolution_request(
520+
self.attr_id,
521+
crate::interface::AttrResolutionRequest { kind, path },
522+
);
512523
}
513524
}
514525

compiler/rustc_attr_parsing/src/interface.rs

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ use std::convert::identity;
33
use rustc_ast as ast;
44
use rustc_ast::token::DocFragmentKind;
55
use rustc_ast::{AttrItemKind, AttrStyle, NodeId, Path, Safety};
6-
use rustc_data_structures::fx::FxIndexMap;
6+
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
77
use rustc_errors::DiagCtxtHandle;
88
use rustc_feature::{AttributeTemplate, Features};
99
use rustc_hir::attrs::{AttrResolution, AttrResolutionKind, AttrResolved, AttributeKind};
1010
use rustc_hir::lints::AttributeLintKind;
1111
use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, Target};
1212
use rustc_session::Session;
1313
use rustc_session::lint::{BuiltinLintDiag, LintId};
14-
use rustc_span::{AttrId, DUMMY_SP, Span, Symbol, sym};
14+
use rustc_span::{AttrId, DUMMY_SP, Ident, Span, Symbol, sym};
1515

1616
use crate::context::{AcceptContext, FinalizeContext, FinalizeFn, SharedContext, Stage};
1717
use crate::early_parsed::{EARLY_PARSED_ATTRIBUTES, EarlyParsedState};
@@ -34,7 +34,7 @@ struct LimitedParseResult {
3434
/// Context created once, for example as part of the ast lowering
3535
/// context, through which all attributes can be lowered.
3636
pub struct AttributeParser<'sess, S: Stage = Late> {
37-
pub(crate) tools: Vec<Symbol>,
37+
pub(crate) tools: Option<&'sess FxIndexSet<Ident>>,
3838
pub(crate) features: Option<&'sess Features>,
3939
pub(crate) sess: &'sess Session,
4040
pub(crate) stage: S,
@@ -101,6 +101,7 @@ impl<'sess> AttributeParser<'sess, Early> {
101101
target_node_id,
102102
features,
103103
should_emit,
104+
None,
104105
)
105106
.attributes;
106107
assert!(parsed.len() <= 1);
@@ -127,6 +128,7 @@ impl<'sess> AttributeParser<'sess, Early> {
127128
target_node_id,
128129
features,
129130
should_emit,
131+
None,
130132
)
131133
.attr_resolution_requests
132134
}
@@ -166,6 +168,7 @@ impl<'sess> AttributeParser<'sess, Early> {
166168
target_node_id: NodeId,
167169
features: Option<&'sess Features>,
168170
emit_errors: ShouldEmit,
171+
tools: Option<&'sess FxIndexSet<Ident>>,
169172
) -> Vec<Attribute> {
170173
Self::parse_limited_inner(
171174
sess,
@@ -176,10 +179,39 @@ impl<'sess> AttributeParser<'sess, Early> {
176179
target_node_id,
177180
features,
178181
emit_errors,
182+
tools,
179183
)
180184
.attributes
181185
}
182186

187+
/// This method provides the same functionality as [`parse_limited_all`](Self::parse_limited_all)
188+
/// except filtered, making sure that only allow-listed symbols are parsed.
189+
pub fn parse_limited_all_filtered(
190+
sess: &'sess Session,
191+
attrs: &[ast::Attribute],
192+
filter: &[Symbol],
193+
target: Target,
194+
target_span: Span,
195+
target_node_id: NodeId,
196+
features: Option<&'sess Features>,
197+
emit_errors: ShouldEmit,
198+
tools: &'sess FxIndexSet<Ident>,
199+
) -> Vec<Attribute> {
200+
let filtered =
201+
attrs.iter().filter(|attr| attr.has_any_name(filter)).cloned().collect::<Vec<_>>();
202+
Self::parse_limited_all(
203+
sess,
204+
&filtered,
205+
None,
206+
target,
207+
target_span,
208+
target_node_id,
209+
features,
210+
emit_errors,
211+
Some(tools),
212+
)
213+
}
214+
183215
fn parse_limited_inner(
184216
sess: &'sess Session,
185217
attrs: &[ast::Attribute],
@@ -189,10 +221,11 @@ impl<'sess> AttributeParser<'sess, Early> {
189221
target_node_id: NodeId,
190222
features: Option<&'sess Features>,
191223
emit_errors: ShouldEmit,
224+
tools: Option<&'sess FxIndexSet<Ident>>,
192225
) -> LimitedParseResult {
193226
let mut p = Self {
194227
features,
195-
tools: Vec::new(),
228+
tools,
196229
parse_only,
197230
sess,
198231
stage: Early { emit_errors },
@@ -285,7 +318,7 @@ impl<'sess> AttributeParser<'sess, Early> {
285318
) -> T {
286319
let mut parser = Self {
287320
features,
288-
tools: Vec::new(),
321+
tools: None,
289322
parse_only: None,
290323
sess,
291324
stage: Early { emit_errors },
@@ -310,7 +343,7 @@ impl<'sess> AttributeParser<'sess, Early> {
310343
target,
311344
emit_lint: &mut emit_lint,
312345
},
313-
attr_id: None,
346+
attr_id: sess.psess.attr_id_generator.mk_attr_id(),
314347
attr_span,
315348
inner_span,
316349
attr_style,
@@ -326,13 +359,13 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
326359
pub fn new(
327360
sess: &'sess Session,
328361
features: &'sess Features,
329-
tools: Vec<Symbol>,
362+
tools: &'sess FxIndexSet<Ident>,
330363
attr_res_map: FxIndexMap<AttrId, Vec<AttrResolution<NodeId>>>,
331364
stage: S,
332365
) -> Self {
333366
Self {
334367
features: Some(features),
335-
tools,
368+
tools: Some(tools),
336369
parse_only: None,
337370
sess,
338371
stage,
@@ -521,7 +554,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
521554
target,
522555
emit_lint: &mut emit_lint,
523556
},
524-
attr_id: Some(attr.id),
557+
attr_id: attr.id,
525558
attr_span,
526559
inner_span: lower_span(n.item.span()),
527560
attr_style: attr.style,
@@ -554,11 +587,9 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
554587

555588
let attr = Attribute::Unparsed(Box::new(attr));
556589

557-
if self.tools.contains(&parts[0])
558-
// FIXME: this can be removed once #152369 has been merged.
559-
// https://github.com/rust-lang/rust/pull/152369
560-
|| [sym::allow, sym::deny, sym::expect, sym::forbid, sym::warn]
561-
.contains(&parts[0])
590+
if self
591+
.tools
592+
.is_some_and(|tools| tools.iter().any(|tool| tool.name == parts[0]))
562593
{
563594
attributes.push(attr);
564595
} else {

compiler/rustc_attr_parsing/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,5 +112,5 @@ pub use attributes::cfg::{
112112
pub use attributes::cfg_select::*;
113113
pub use attributes::util::{is_builtin_attr, parse_version};
114114
pub use context::{Early, Late, OmitDoc, ShouldEmit};
115-
pub use interface::AttributeParser;
115+
pub use interface::{AttrResolutionRequest, AttributeParser};
116116
pub use session_diagnostics::ParsedDescription;

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,16 +184,35 @@ pub enum AttrIntValue {
184184
Const { def_id: DefId, span: Span },
185185
}
186186

187+
/// The resolution strategy a parsed builtin attribute argument expects.
188+
#[derive(
189+
Copy,
190+
Clone,
191+
Debug,
192+
PartialEq,
193+
Eq,
194+
HashStable_Generic,
195+
Encodable,
196+
Decodable,
197+
PrintAttribute
198+
)]
199+
pub enum AttrResolutionKind {
200+
Const,
201+
}
202+
203+
/// A resolved attribute argument path, or an error placeholder if resolution failed.
187204
#[derive(Debug, Copy, Clone, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
188-
pub enum AttrConstResolved<Id = ast::NodeId> {
205+
pub enum AttrResolved<Id = ast::NodeId> {
189206
Resolved(Res<Id>),
190207
Error,
191208
}
192209

210+
/// A resolved attribute argument path produced by late resolution for a builtin attribute.
193211
#[derive(Debug, Copy, Clone, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
194-
pub struct AttrConstResolution<Id = ast::NodeId> {
212+
pub struct AttrResolution<Id = ast::NodeId> {
213+
pub kind: AttrResolutionKind,
195214
pub path_span: Span,
196-
pub resolved: AttrConstResolved<Id>,
215+
pub resolved: AttrResolved<Id>,
197216
}
198217

199218
pub enum TransparencyError {

compiler/rustc_hir/src/attrs/pretty_printing.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
1717
use rustc_target::spec::SanitizerSet;
1818
use thin_vec::ThinVec;
1919

20-
use crate::attrs::AttrIntValue;
20+
use crate::HashIgnoredAttrId;
21+
use crate::attrs::{AttrIntValue, LintInstance};
2122
use crate::limit::Limit;
2223

2324
/// This trait is used to print attributes in `rustc_hir_pretty`.
@@ -205,8 +206,8 @@ macro_rules! print_tup {
205206
}
206207

207208
print_tup!(A B C D E F G H);
208-
print_skip!(Span, (), ErrorGuaranteed, AttrId);
209-
print_disp!(u8, u16, u32, u128, usize, bool, NonZero<u32>, Limit);
209+
print_skip!(Span, (), ErrorGuaranteed, AttrId, HashIgnoredAttrId);
210+
print_disp!(u8, u16, u32, u128, usize, bool, NonZero<u32>, Limit, LintInstance);
210211
print_debug!(
211212
Symbol,
212213
Ident,

0 commit comments

Comments
 (0)