Skip to content

Commit 690d85b

Browse files
committed
refactor: more general terminology and use existing attr parse machinery
1 parent 7e3bc2e commit 690d85b

File tree

9 files changed

+102
-114
lines changed

9 files changed

+102
-114
lines changed

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -654,8 +654,8 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> mid_hir::Crate<'_> {
654654

655655
for def_id in ast_index.indices() {
656656
match &ast_index[def_id] {
657-
AstOwner::Item(Item { kind: ItemKind::Delegation { .. }, .. })
658-
| AstOwner::AssocItem(Item { kind: AssocItemKind::Delegation { .. }, .. }, _) => {
657+
AstOwner::Item(Item { kind: ItemKind::Delegation(..), .. })
658+
| AstOwner::AssocItem(Item { kind: AssocItemKind::Delegation(..), .. }, _) => {
659659
delayed_ids.insert(def_id);
660660
}
661661
_ => lowerer.lower_node(def_id),

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: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ use crate::attributes::dummy::*;
3838
use crate::attributes::inline::*;
3939
use crate::attributes::instruction_set::*;
4040
use crate::attributes::link_attrs::*;
41-
use crate::attributes::lint::*;
4241
use crate::attributes::lint_helpers::*;
4342
use crate::attributes::loop_match::*;
4443
use crate::attributes::macro_attrs::*;
@@ -151,7 +150,6 @@ attribute_parsers!(
151150
ConfusablesParser,
152151
ConstStabilityParser,
153152
DocParser,
154-
LintParser,
155153
MacroUseParser,
156154
NakedParser,
157155
OnConstParser,
@@ -887,17 +885,6 @@ where
887885
)
888886
}
889887

890-
pub(crate) fn expected_nv_as_last_argument(
891-
&mut self,
892-
span: Span,
893-
name_value_key: Symbol,
894-
) -> ErrorGuaranteed {
895-
self.emit_parse_error(
896-
span,
897-
AttributeParseErrorReason::ExpectedNameValueAsLastArgument { span, name_value_key },
898-
)
899-
}
900-
901888
pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
902889
let attr_path = self.attr_path.clone().to_string();
903890
let valid_without_list = self.template.word;

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
@@ -182,16 +182,35 @@ pub enum AttrIntValue {
182182
Const { def_id: DefId, span: Span },
183183
}
184184

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

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

197216
pub enum TransparencyError {

compiler/rustc_hir/src/attrs/pretty_printing.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_target::spec::SanitizerSet;
1818
use thin_vec::ThinVec;
1919

2020
use crate::HashIgnoredAttrId;
21-
use crate::attrs::{AttrIntValue, LintInstance};
21+
use crate::attrs::AttrIntValue;
2222
use crate::limit::Limit;
2323

2424
/// This trait is used to print attributes in `rustc_hir_pretty`.
@@ -207,7 +207,7 @@ macro_rules! print_tup {
207207

208208
print_tup!(A B C D E F G H);
209209
print_skip!(Span, (), ErrorGuaranteed, AttrId, HashIgnoredAttrId);
210-
print_disp!(u8, u16, u32, u128, usize, bool, NonZero<u32>, Limit, LintInstance);
210+
print_disp!(u8, u16, u32, u128, usize, bool, NonZero<u32>, Limit);
211211
print_debug!(
212212
Symbol,
213213
Ident,

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use rustc_data_structures::steal::Steal;
3737
use rustc_data_structures::unord::{UnordMap, UnordSet};
3838
use rustc_errors::{Diag, ErrorGuaranteed, LintBuffer};
3939
use rustc_hir as hir;
40-
use rustc_hir::attrs::{AttrConstResolution, StrippedCfgItem};
40+
use rustc_hir::attrs::{AttrResolution, StrippedCfgItem};
4141
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
4242
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
4343
use rustc_hir::{LangItem, attrs as attr, find_attr};
@@ -211,8 +211,9 @@ pub struct ResolverAstLowering<'tcx> {
211211
pub lifetimes_res_map: NodeMap<LifetimeRes>,
212212
/// Lifetime parameters that lowering will have to introduce.
213213
pub extra_lifetime_params_map: NodeMap<Vec<(Ident, ast::NodeId, LifetimeRes)>>,
214-
/// Resolutions for const item paths used in opted-in late attributes, keyed by attribute ID.
215-
pub attr_const_res_map: FxIndexMap<AttrId, Vec<AttrConstResolution<ast::NodeId>>>,
214+
/// Resolutions for builtin attribute arguments that need late name resolution, keyed by
215+
/// attribute ID.
216+
pub attr_res_map: FxIndexMap<AttrId, Vec<AttrResolution<ast::NodeId>>>,
216217

217218
pub next_node_id: ast::NodeId,
218219

compiler/rustc_resolve/src/late.rs

Lines changed: 41 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@
88
99
use std::borrow::Cow;
1010
use std::collections::hash_map::Entry;
11-
use std::debug_assert_matches;
1211
use std::mem::{replace, swap, take};
1312
use std::ops::{ControlFlow, Range};
13+
use std::{debug_assert_matches, slice};
1414

1515
use rustc_ast::visit::{
1616
AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, try_visit, visit_opt, walk_list,
1717
};
1818
use rustc_ast::*;
19+
use rustc_attr_parsing::{AttrResolutionRequest, AttributeParser};
1920
use rustc_data_structures::either::Either;
2021
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
2122
use rustc_data_structures::unord::{UnordMap, UnordSet};
@@ -24,7 +25,7 @@ use rustc_errors::{
2425
Applicability, Diag, DiagArgValue, Diagnostic, ErrorGuaranteed, IntoDiagArg, MultiSpan,
2526
StashKey, Suggestions, elided_lifetime_in_path_suggestion, pluralize,
2627
};
27-
use rustc_hir::attrs::AttrConstResolved;
28+
use rustc_hir::attrs::AttrResolved;
2829
use rustc_hir::def::Namespace::{self, *};
2930
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
3031
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId};
@@ -826,7 +827,7 @@ struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
826827
/// Walks the whole crate in DFS order, visiting each item, resolving names as it goes.
827828
impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
828829
fn visit_attribute(&mut self, attr: &'ast Attribute) {
829-
self.resolve_attr_const_paths(attr);
830+
self.resolve_attr_paths(attr);
830831
}
831832
fn visit_item(&mut self, item: &'ast Item) {
832833
let prev = replace(&mut self.diag_metadata.current_item, Some(item));
@@ -1471,65 +1472,37 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc
14711472
}
14721473

14731474
impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
1474-
fn resolve_attr_const_paths(&mut self, attr: &'ast Attribute) {
1475-
match attr.name() {
1476-
Some(sym::repr) => {
1477-
let Some(items) = attr.meta_item_list() else {
1478-
return;
1479-
};
1480-
for item in &items {
1481-
let Some(meta) = item.meta_item() else {
1482-
continue;
1483-
};
1484-
let Some(name) = meta.name() else {
1485-
continue;
1486-
};
1487-
if !matches!(name, sym::align | sym::packed) {
1488-
continue;
1489-
}
1490-
let Some([arg]) = meta.meta_item_list() else {
1491-
continue;
1492-
};
1493-
let Some(path_meta) = arg.meta_item() else {
1494-
continue;
1495-
};
1496-
if !path_meta.is_word() {
1497-
continue;
1498-
}
1499-
if !self.should_resolve_attr_const_path(path_meta.path.span) {
1500-
continue;
1501-
}
1502-
self.resolve_attr_const_path(attr.id, &path_meta.path);
1503-
}
1504-
}
1505-
Some(sym::rustc_align | sym::rustc_align_static) => {
1506-
let Some(items) = attr.meta_item_list() else {
1507-
return;
1508-
};
1509-
let [arg] = items.as_slice() else {
1510-
return;
1511-
};
1512-
let Some(path_meta) = arg.meta_item() else {
1513-
return;
1514-
};
1515-
if !path_meta.is_word() {
1516-
return;
1517-
}
1518-
if !self.should_resolve_attr_const_path(path_meta.path.span) {
1519-
return;
1520-
}
1521-
self.resolve_attr_const_path(attr.id, &path_meta.path);
1522-
}
1523-
_ => {}
1475+
fn resolve_attr_paths(&mut self, attr: &'ast Attribute) {
1476+
let Some(name) = attr.name() else {
1477+
return;
1478+
};
1479+
if !matches!(name, sym::repr | sym::rustc_align | sym::rustc_align_static) {
1480+
return;
15241481
}
1525-
}
15261482

1527-
fn should_resolve_attr_const_path(&self, span: Span) -> bool {
1528-
self.r.tcx.features().const_attr_paths() || span.allows_unstable(sym::const_attr_paths)
1483+
let parse_only = match name {
1484+
sym::repr => &[sym::repr][..],
1485+
sym::rustc_align => &[sym::rustc_align][..],
1486+
sym::rustc_align_static => &[sym::rustc_align_static][..],
1487+
_ => unreachable!(),
1488+
};
1489+
1490+
let mut requests = AttributeParser::parse_limited_attr_resolution_requests(
1491+
self.r.tcx.sess,
1492+
slice::from_ref(attr),
1493+
parse_only,
1494+
attr.span,
1495+
DUMMY_NODE_ID,
1496+
Some(self.r.tcx.features()),
1497+
);
1498+
for request in requests.shift_remove(&attr.id).into_iter().flatten() {
1499+
self.resolve_attr_path(attr.id, request);
1500+
}
15291501
}
15301502

1531-
fn resolve_attr_const_path(&mut self, attr_id: AttrId, path: &Path) {
1532-
let path_segments = path
1503+
fn resolve_attr_path(&mut self, attr_id: AttrId, request: AttrResolutionRequest) {
1504+
let path_segments = request
1505+
.path
15331506
.segments
15341507
.iter()
15351508
.map(|segment| Segment::from_ident(segment.ident))
@@ -1538,19 +1511,21 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
15381511
&None,
15391512
&path_segments,
15401513
PathSource::Expr(None),
1541-
Finalize::new(DUMMY_NODE_ID, path.span),
1514+
Finalize::new(DUMMY_NODE_ID, request.path.span),
15421515
RecordPartialRes::No,
15431516
None,
15441517
);
15451518
let resolved = match partial_res.full_res() {
1546-
Some(Res::Err) | None => AttrConstResolved::Error,
1547-
Some(res) => AttrConstResolved::Resolved(res),
1519+
Some(Res::Err) | None => AttrResolved::Error,
1520+
Some(res) => AttrResolved::Resolved(res),
15481521
};
1549-
self.r
1550-
.attr_const_resolutions
1551-
.entry(attr_id)
1552-
.or_default()
1553-
.push(rustc_hir::attrs::AttrConstResolution { path_span: path.span, resolved });
1522+
self.r.attr_resolutions.entry(attr_id).or_default().push(
1523+
rustc_hir::attrs::AttrResolution {
1524+
kind: request.kind,
1525+
path_span: request.path.span,
1526+
resolved,
1527+
},
1528+
);
15541529
}
15551530
}
15561531

0 commit comments

Comments
 (0)