Skip to content

Commit 799d605

Browse files
Rewrite the new attribute parser
Signed-off-by: Jonathan Brouwer <[email protected]>
1 parent cdc5b94 commit 799d605

22 files changed

+376
-375
lines changed

compiler/rustc_attr_parsing/messages.ftl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,3 +173,9 @@ attr_parsing_invalid_attr_unsafe = `{$name}` is not an unsafe attribute
173173
.label = this is not an unsafe attribute
174174
.suggestion = remove the `unsafe(...)`
175175
.note = extraneous unsafe is not allowed in attributes
176+
177+
attr_parsing_invalid_meta_item = expected unsuffixed literal, found {$descr}
178+
.quote_ident_sugg = surround the identifier with quotation marks to make it into a string literal
179+
180+
attr_parsing_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes
181+
.help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::borrow::Cow;
12
use std::cell::RefCell;
23
use std::collections::BTreeMap;
34
use std::ops::{Deref, DerefMut};
@@ -213,7 +214,6 @@ mod private {
213214
#[allow(private_interfaces)]
214215
pub trait Stage: Sized + 'static + Sealed {
215216
type Id: Copy;
216-
const SHOULD_EMIT_LINTS: bool;
217217

218218
fn parsers() -> &'static group_type!(Self);
219219

@@ -222,13 +222,14 @@ pub trait Stage: Sized + 'static + Sealed {
222222
sess: &'sess Session,
223223
diag: impl for<'x> Diagnostic<'x>,
224224
) -> ErrorGuaranteed;
225+
226+
fn should_emit(&self) -> ShouldEmit;
225227
}
226228

227229
// allow because it's a sealed trait
228230
#[allow(private_interfaces)]
229231
impl Stage for Early {
230232
type Id = NodeId;
231-
const SHOULD_EMIT_LINTS: bool = false;
232233

233234
fn parsers() -> &'static group_type!(Self) {
234235
&early::ATTRIBUTE_PARSERS
@@ -244,13 +245,16 @@ impl Stage for Early {
244245
sess.dcx().create_err(diag).delay_as_bug()
245246
}
246247
}
248+
249+
fn should_emit(&self) -> ShouldEmit {
250+
self.emit_errors
251+
}
247252
}
248253

249254
// allow because it's a sealed trait
250255
#[allow(private_interfaces)]
251256
impl Stage for Late {
252257
type Id = HirId;
253-
const SHOULD_EMIT_LINTS: bool = true;
254258

255259
fn parsers() -> &'static group_type!(Self) {
256260
&late::ATTRIBUTE_PARSERS
@@ -262,6 +266,10 @@ impl Stage for Late {
262266
) -> ErrorGuaranteed {
263267
tcx.dcx().emit_err(diag)
264268
}
269+
270+
fn should_emit(&self) -> ShouldEmit {
271+
ShouldEmit::ErrorsAndLints
272+
}
265273
}
266274

267275
/// used when parsing attributes for miscellaneous things *before* ast lowering
@@ -300,7 +308,7 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
300308
/// must be delayed until after HIR is built. This method will take care of the details of
301309
/// that.
302310
pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
303-
if !S::SHOULD_EMIT_LINTS {
311+
if !self.stage.should_emit().should_emit() {
304312
return;
305313
}
306314
let id = self.target_id;
@@ -686,9 +694,9 @@ impl<'sess> AttributeParser<'sess, Early> {
686694
target_node_id: NodeId,
687695
features: Option<&'sess Features>,
688696
emit_errors: ShouldEmit,
689-
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> T,
697+
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> Option<T>,
690698
template: &AttributeTemplate,
691-
) -> T {
699+
) -> Option<T> {
692700
let mut parser = Self {
693701
features,
694702
tools: Vec::new(),
@@ -699,7 +707,7 @@ impl<'sess> AttributeParser<'sess, Early> {
699707
let ast::AttrKind::Normal(normal_attr) = &attr.kind else {
700708
panic!("parse_single called on a doc attr")
701709
};
702-
let meta_parser = MetaItemParser::from_attr(normal_attr, &sess.psess);
710+
let meta_parser = MetaItemParser::from_attr(normal_attr, &sess.psess, emit_errors)?;
703711
let path = meta_parser.path();
704712
let args = meta_parser.args();
705713
let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
@@ -804,14 +812,22 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
804812
// }))
805813
// }
806814
ast::AttrKind::Normal(n) => {
807-
attr_paths.push(PathParser::Ast(&n.item.path));
815+
attr_paths.push(PathParser(Cow::Borrowed(&n.item.path)));
808816

809-
let parser = MetaItemParser::from_attr(n, &self.sess.psess);
810-
let path = parser.path();
811-
let args = parser.args();
812-
let parts = path.segments().map(|i| i.name).collect::<Vec<_>>();
817+
let parts =
818+
n.item.path.segments.iter().map(|seg| seg.ident.name).collect::<Vec<_>>();
813819

814820
if let Some(accepts) = S::parsers().0.get(parts.as_slice()) {
821+
let Some(parser) = MetaItemParser::from_attr(
822+
n,
823+
&self.sess.psess,
824+
self.stage.should_emit(),
825+
) else {
826+
continue;
827+
};
828+
let path = parser.path();
829+
let args = parser.args();
830+
815831
for (template, accept) in accepts {
816832
let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext {
817833
shared: SharedContext {

0 commit comments

Comments
 (0)