Skip to content

Refactor attribute parsing to improve ergonomics and some diagnostics #145507

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3480,7 +3480,6 @@ dependencies = [
name = "rustc_attr_parsing"
version = "0.0.0"
dependencies = [
"itertools",
"rustc_abi",
"rustc_ast",
"rustc_ast_pretty",
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_attr_parsing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ edition = "2024"

[dependencies]
# tidy-alphabetical-start
itertools = "0.12"
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
Expand Down
10 changes: 1 addition & 9 deletions compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
use std::iter;

use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::{MethodKind, Target};
use rustc_span::{Span, Symbol, sym};

use super::{CombineAttributeParser, ConvertFn};
use crate::context::MaybeWarn::{Allow, Warn};
use crate::context::{AcceptContext, AllowedTargets, Stage};
use crate::parser::ArgParser;
use super::prelude::*;
use crate::session_diagnostics;

pub(crate) struct AllowInternalUnstableParser;
Expand Down
8 changes: 1 addition & 7 deletions compiler/rustc_attr_parsing/src/attributes/body.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
//! Attributes that can be found in function body.

use rustc_hir::Target;
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Symbol, sym};

use super::{NoArgsAttributeParser, OnDuplicate};
use crate::context::MaybeWarn::Allow;
use crate::context::{AllowedTargets, Stage};
use super::prelude::*;

pub(crate) struct CoroutineParser;

Expand Down
15 changes: 3 additions & 12 deletions compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::{AttributeKind, CoverageAttrKind, OptimizeAttr, UsedBy};
use rustc_hir::{MethodKind, Target};
use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, UsedBy};
use rustc_session::parse::feature_err;
use rustc_span::{Span, Symbol, sym};

use super::{
AcceptMapping, AttributeOrder, AttributeParser, CombineAttributeParser, ConvertFn,
NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
};
use crate::context::MaybeWarn::{Allow, Warn};
use crate::context::{AcceptContext, AllowedTargets, FinalizeContext, Stage};
use crate::parser::ArgParser;

use super::prelude::*;
use crate::session_diagnostics::{NakedFunctionIncompatibleAttribute, NullOnExport};

pub(crate) struct OptimizeParser;
Expand Down
15 changes: 4 additions & 11 deletions compiler/rustc_attr_parsing/src/attributes/confusables.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
use rustc_feature::template;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::{MethodKind, Target};
use rustc_span::{Span, Symbol, sym};
use thin_vec::ThinVec;

use super::{AcceptMapping, AttributeParser};
use crate::context::MaybeWarn::Allow;
use crate::context::{AllowedTargets, FinalizeContext, Stage};
use crate::session_diagnostics;
use super::prelude::*;
use crate::session_diagnostics::EmptyConfusables;

#[derive(Default)]
pub(crate) struct ConfusablesParser {
confusables: ThinVec<Symbol>,
Expand All @@ -25,7 +18,7 @@ impl<S: Stage> AttributeParser<S> for ConfusablesParser {
};

if list.is_empty() {
cx.emit_err(session_diagnostics::EmptyConfusables { span: cx.attr_span });
cx.emit_err(EmptyConfusables { span: cx.attr_span });
}

for param in list.mixed() {
Expand Down
23 changes: 10 additions & 13 deletions compiler/rustc_attr_parsing/src/attributes/deprecation.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::{AttributeKind, DeprecatedSince, Deprecation};
use rustc_hir::{MethodKind, Target};
use rustc_span::{Span, Symbol, sym};
use rustc_hir::attrs::{DeprecatedSince, Deprecation};

use super::prelude::*;
use super::util::parse_version;
use super::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::MaybeWarn::{Allow, Error};
use crate::context::{AcceptContext, AllowedTargets, Stage};
use crate::parser::ArgParser;
use crate::session_diagnostics;
use crate::session_diagnostics::{
DeprecatedItemSuggestion, InvalidSince, MissingNote, MissingSince,
};

pub(crate) struct DeprecationParser;

fn get<S: Stage>(
Expand Down Expand Up @@ -102,7 +99,7 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
}
Some(name @ sym::suggestion) => {
if !features.deprecated_suggestion() {
cx.emit_err(session_diagnostics::DeprecatedItemSuggestion {
cx.emit_err(DeprecatedItemSuggestion {
span: param.span(),
is_nightly: cx.sess().is_nightly_build(),
details: (),
Expand Down Expand Up @@ -144,18 +141,18 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
} else if let Some(version) = parse_version(since) {
DeprecatedSince::RustcVersion(version)
} else {
cx.emit_err(session_diagnostics::InvalidSince { span: cx.attr_span });
cx.emit_err(InvalidSince { span: cx.attr_span });
DeprecatedSince::Err
}
} else if is_rustc {
cx.emit_err(session_diagnostics::MissingSince { span: cx.attr_span });
cx.emit_err(MissingSince { span: cx.attr_span });
DeprecatedSince::Err
} else {
DeprecatedSince::Unspecified
};

if is_rustc && note.is_none() {
cx.emit_err(session_diagnostics::MissingNote { span: cx.attr_span });
cx.emit_err(MissingNote { span: cx.attr_span });
return None;
}

Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_attr_parsing/src/attributes/dummy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ use rustc_hir::attrs::AttributeKind;
use rustc_span::{Symbol, sym};

use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, Stage};
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
use crate::target_checking::{ALL_TARGETS, AllowedTargets};

pub(crate) struct DummyParser;
impl<S: Stage> SingleAttributeParser<S> for DummyParser {
const PATH: &[Symbol] = &[sym::rustc_dummy];
Expand Down
11 changes: 2 additions & 9 deletions compiler/rustc_attr_parsing/src/attributes/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,10 @@
// note: need to model better how duplicate attr errors work when not using
// SingleAttributeParser which is what we have two of here.

use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::{AttributeKind, InlineAttr};
use rustc_hir::lints::AttributeLintKind;
use rustc_hir::{MethodKind, Target};
use rustc_span::{Symbol, sym};

use super::{AcceptContext, AttributeOrder, OnDuplicate};
use crate::attributes::SingleAttributeParser;
use crate::context::MaybeWarn::{Allow, Warn};
use crate::context::{AllowedTargets, Stage};
use crate::parser::ArgParser;
use super::prelude::*;

pub(crate) struct InlineParser;

impl<S: Stage> SingleAttributeParser<S> for InlineParser {
Expand Down
16 changes: 5 additions & 11 deletions compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection};
use rustc_hir::attrs::{AttributeKind, Linkage};
use rustc_hir::{MethodKind, Target};
use rustc_span::{Span, Symbol, sym};

use crate::attributes::{
AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
};
use crate::context::MaybeWarn::Allow;
use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, Stage, parse_single_integer};
use crate::parser::ArgParser;
use rustc_hir::attrs::Linkage;

use super::prelude::*;
use super::util::parse_single_integer;
use crate::session_diagnostics::{LinkOrdinalOutOfRange, NullOnLinkSection};

pub(crate) struct LinkNameParser;

impl<S: Stage> SingleAttributeParser<S> for LinkNameParser {
Expand Down
7 changes: 1 addition & 6 deletions compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
use rustc_hir::attrs::AttributeKind;
use rustc_hir::{MethodKind, Target};
use rustc_span::{Span, Symbol, sym};
use super::prelude::*;

use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
use crate::context::MaybeWarn::{Allow, Error};
use crate::context::{AllowedTargets, Stage};
pub(crate) struct AsPtrParser;
impl<S: Stage> NoArgsAttributeParser<S> for AsPtrParser {
const PATH: &[Symbol] = &[sym::rustc_as_ptr];
Expand Down
7 changes: 1 addition & 6 deletions compiler/rustc_attr_parsing/src/attributes/loop_match.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
use rustc_hir::Target;
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Span, Symbol, sym};
use super::prelude::*;

use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
use crate::context::MaybeWarn::Allow;
use crate::context::{AllowedTargets, Stage};
pub(crate) struct LoopMatchParser;
impl<S: Stage> NoArgsAttributeParser<S> for LoopMatchParser {
const PATH: &[Symbol] = &[sym::loop_match];
Expand Down
16 changes: 5 additions & 11 deletions compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
use rustc_errors::DiagArgValue;
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::Target;
use rustc_hir::attrs::{AttributeKind, MacroUseArgs};
use rustc_span::{Span, Symbol, sym};
use thin_vec::ThinVec;
use rustc_hir::attrs::MacroUseArgs;

use super::prelude::*;
use crate::session_diagnostics::IllFormedAttributeInputLint;

use crate::attributes::{AcceptMapping, AttributeParser, NoArgsAttributeParser, OnDuplicate};
use crate::context::MaybeWarn::{Allow, Error, Warn};
use crate::context::{AcceptContext, AllowedTargets, FinalizeContext, Stage};
use crate::parser::ArgParser;
use crate::session_diagnostics;
pub(crate) struct MacroEscapeParser;
impl<S: Stage> NoArgsAttributeParser<S> for MacroEscapeParser {
const PATH: &[Symbol] = &[sym::macro_escape];
Expand Down Expand Up @@ -108,7 +102,7 @@ impl<S: Stage> AttributeParser<S> for MacroUseParser {
}
ArgParser::NameValue(_) => {
let suggestions = MACRO_USE_TEMPLATE.suggestions(cx.attr_style, sym::macro_use);
cx.emit_err(session_diagnostics::IllFormedAttributeInputLint {
cx.emit_err(IllFormedAttributeInputLint {
num_suggestions: suggestions.len(),
suggestions: DiagArgValue::StrListSepByAnd(
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
Expand Down
10 changes: 7 additions & 3 deletions compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
//! Specifically, you might not care about managing the state of your [`AttributeParser`]
//! state machine yourself. In this case you can choose to implement:
//!
//! - [`SingleAttributeParser`]: makes it easy to implement an attribute which should error if it
//! - [`SingleAttributeParser`](crate::attributes::SingleAttributeParser): makes it easy to implement an attribute which should error if it
//! appears more than once in a list of attributes
//! - [`CombineAttributeParser`]: makes it easy to implement an attribute which should combine the
//! - [`CombineAttributeParser`](crate::attributes::CombineAttributeParser): makes it easy to implement an attribute which should combine the
//! contents of attributes, if an attribute appear multiple times in a list
//!
//! Attributes should be added to `crate::context::ATTRIBUTE_PARSERS` to be parsed.
Expand All @@ -21,9 +21,13 @@ use rustc_hir::attrs::AttributeKind;
use rustc_span::{Span, Symbol};
use thin_vec::ThinVec;

use crate::context::{AcceptContext, AllowedTargets, FinalizeContext, Stage};
use crate::context::{AcceptContext, FinalizeContext, Stage};
use crate::parser::ArgParser;
use crate::session_diagnostics::UnusedMultiple;
use crate::target_checking::AllowedTargets;

/// All the parsers require roughly the same imports, so this prelude has most of the often-needed ones.
mod prelude;

pub(crate) mod allow_unstable;
pub(crate) mod body;
Expand Down
12 changes: 4 additions & 8 deletions compiler/rustc_attr_parsing/src/attributes/must_use.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
use rustc_errors::DiagArgValue;
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Symbol, sym};

use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, Stage};
use crate::parser::ArgParser;
use crate::session_diagnostics;
use super::prelude::*;
use crate::session_diagnostics::IllFormedAttributeInputLint;

pub(crate) struct MustUseParser;

impl<S: Stage> SingleAttributeParser<S> for MustUseParser {
Expand Down Expand Up @@ -37,7 +33,7 @@ impl<S: Stage> SingleAttributeParser<S> for MustUseParser {
ArgParser::List(_) => {
let suggestions = <Self as SingleAttributeParser<S>>::TEMPLATE
.suggestions(cx.attr_style, "must_use");
cx.emit_err(session_diagnostics::IllFormedAttributeInputLint {
cx.emit_err(IllFormedAttributeInputLint {
num_suggestions: suggestions.len(),
suggestions: DiagArgValue::StrListSepByAnd(
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
use rustc_hir::Target;
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Span, sym};
use super::prelude::*;

use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
use crate::context::MaybeWarn::Allow;
use crate::context::{AllowedTargets, Stage};
pub(crate) struct NoImplicitPreludeParser;

impl<S: Stage> NoArgsAttributeParser<S> for NoImplicitPreludeParser {
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ use rustc_hir::attrs::AttributeKind;
use rustc_span::{Span, Symbol, sym};

use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
use crate::context::MaybeWarn::{Allow, Warn};
use crate::context::{AllowedTargets, Stage};
use crate::context::Stage;
use crate::target_checking::AllowedTargets;
use crate::target_checking::Policy::{Allow, Warn};

pub(crate) struct NonExhaustiveParser;

impl<S: Stage> NoArgsAttributeParser<S> for NonExhaustiveParser {
Expand Down
9 changes: 1 addition & 8 deletions compiler/rustc_attr_parsing/src/attributes/path.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::Target;
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Symbol, sym};
use super::prelude::*;

use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::MaybeWarn::{Allow, Error};
use crate::context::{AcceptContext, AllowedTargets, Stage};
use crate::parser::ArgParser;
pub(crate) struct PathParser;

impl<S: Stage> SingleAttributeParser<S> for PathParser {
Expand Down
20 changes: 20 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/prelude.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// parsing
// templates
pub(super) use rustc_feature::{AttributeTemplate, template};
// data structures
pub(super) use rustc_hir::attrs::AttributeKind;
pub(super) use rustc_hir::lints::AttributeLintKind;
pub(super) use rustc_hir::{MethodKind, Target};
pub(super) use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym};
pub(super) use thin_vec::ThinVec;

pub(super) use crate::attributes::{
AcceptMapping, AttributeOrder, AttributeParser, CombineAttributeParser, ConvertFn,
NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
};
// contexts
pub(super) use crate::context::{AcceptContext, FinalizeContext, Stage};
pub(super) use crate::parser::*;
// target checking
pub(super) use crate::target_checking::Policy::{Allow, Error, Warn};
pub(super) use crate::target_checking::{ALL_TARGETS, AllowedTargets};
12 changes: 1 addition & 11 deletions compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::Target;
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Span, Symbol, sym};
use thin_vec::ThinVec;
use super::prelude::*;

use crate::attributes::{
AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
};
use crate::context::MaybeWarn::{Allow, Warn};
use crate::context::{AcceptContext, AllowedTargets, Stage};
use crate::parser::ArgParser;
pub(crate) struct ProcMacroParser;
impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroParser {
const PATH: &[Symbol] = &[sym::proc_macro];
Expand Down
Loading
Loading