Skip to content

Rewrite inline attr parsing #6

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 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
aac585d
create variant for inline
jdonszelmann Feb 6, 2025
ccd995b
install a blank parser
jdonszelmann Feb 6, 2025
f439e02
introduce reject duplicate strategy
jdonszelmann Feb 6, 2025
2b4c12b
default error on single attribute parsers
jdonszelmann Feb 6, 2025
694a777
start using the first rejection strategy
jdonszelmann Feb 6, 2025
4234d2d
rename
jdonszelmann Feb 6, 2025
cb31ca6
add future warn preceding strategy
jdonszelmann Feb 6, 2025
b2c7182
remove default
jdonszelmann Feb 6, 2025
248ab8f
new on duplicate enum
jdonszelmann Feb 6, 2025
68976b2
use OnDuplicate for all existing single parsers
jdonszelmann Feb 6, 2025
828ebdb
convert DUPLICATE_STRATEGY into attribute order
jdonszelmann Feb 6, 2025
29c3315
implement inline parser
jdonszelmann Feb 6, 2025
0cb2891
rename future error
jdonszelmann Feb 6, 2025
336587c
convert entire codebase to parsed inline attrs
jdonszelmann Feb 6, 2025
cfbcc72
make lints possible in attr lowering
jdonszelmann Feb 12, 2025
c06e77b
depend more on attr_data_structures and move find_attr! there
jdonszelmann Feb 12, 2025
721a706
implement duplicate attr lints
jdonszelmann Feb 28, 2025
5768ea5
edit mailmap
jdonszelmann Mar 2, 2025
6d30004
hopefully implement lints during attr parsing
jdonszelmann Mar 3, 2025
5542dba
convert rustc_force_inline
jdonszelmann Mar 3, 2025
2d0754a
add error message for unused duplicate
jdonszelmann Mar 3, 2025
8a64946
fix most bugs in inline attribute parsing
jdonszelmann Mar 4, 2025
e0690b8
implement consistent errors for attributes (and update `inline`)
jdonszelmann Mar 4, 2025
245ed33
use consistent attr errors in more places
jdonszelmann Mar 5, 2025
e903b10
change errors to be more consistent across parsed attributes
jdonszelmann Mar 5, 2025
49b8b6c
tidy
jdonszelmann Mar 5, 2025
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
5 changes: 4 additions & 1 deletion .mailmap
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ Jacob Greenfield <[email protected]>
Jacob Pratt <[email protected]> <[email protected]>
Jacob Pratt <[email protected]> <[email protected]>
Jake Goulding <[email protected]>
Jake Goulding <[email protected]> <[email protected]>
Jake Goulding <[email protected]> <[email protected]>
Jake Goulding <[email protected]> <[email protected]>
Jake Vossen <[email protected]>
Jakob Degen <[email protected]> <[email protected]>
Expand All @@ -292,6 +292,9 @@ James Hinshelwood <[email protected]> <[email protected]>
James Miller <[email protected]> <[email protected]>
James Perry <[email protected]>
James Sanderson <[email protected]>
Jana Dönszelmann <[email protected]>
Jana Dönszelmann <[email protected]> <[email protected]>
Jana Dönszelmann <[email protected]> <[email protected]>
Jan-Erik Rediger <[email protected]> <[email protected]>
Jaro Fietz <[email protected]>
Jason Fager <[email protected]>
Expand Down
6 changes: 4 additions & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3286,6 +3286,7 @@ dependencies = [
"rustc_hir",
"rustc_lexer",
"rustc_macros",
"rustc_middle",
"rustc_serialize",
"rustc_session",
"rustc_span",
Expand Down Expand Up @@ -3741,7 +3742,7 @@ dependencies = [
"rustc_abi",
"rustc_ast",
"rustc_ast_pretty",
"rustc_attr_parsing",
"rustc_attr_data_structures",
"rustc_hir",
"rustc_span",
]
Expand Down Expand Up @@ -4008,7 +4009,8 @@ dependencies = [
"rustc_apfloat",
"rustc_arena",
"rustc_ast",
"rustc_attr_parsing",
"rustc_ast_ir",
"rustc_attr_data_structures",
"rustc_data_structures",
"rustc_error_messages",
"rustc_errors",
Expand Down
16 changes: 7 additions & 9 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Merge attributes into the inner expression.
if !e.attrs.is_empty() {
let old_attrs = self.attrs.get(&ex.hir_id.local_id).copied().unwrap_or(&[]);
self.attrs.insert(
ex.hir_id.local_id,
&*self.arena.alloc_from_iter(
self.lower_attrs_vec(&e.attrs, e.span)
.into_iter()
.chain(old_attrs.iter().cloned()),
),
);
let new_attrs = self
.lower_attrs_vec(&e.attrs, e.span, ex.hir_id)
.into_iter()
.chain(old_attrs.iter().cloned());
self.attrs
.insert(ex.hir_id.local_id, &*self.arena.alloc_from_iter(new_attrs));
}
return ex;
}
Expand Down Expand Up @@ -2024,7 +2022,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let ret_expr = self.checked_return(Some(from_residual_expr));
self.arena.alloc(self.expr(try_span, ret_expr))
};
self.lower_attrs(ret_expr.hir_id, &attrs, ret_expr.span);
self.lower_attrs(ret_expr.hir_id, &attrs, span);

let break_pat = self.pat_cf_break(try_span, residual_local);
self.arm(break_pat, ret_expr)
Expand Down
51 changes: 40 additions & 11 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// interact with `gen`/`async gen` blocks
allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),

attribute_parser: AttributeParser::new(tcx.sess, tcx.features(), registered_tools),
attribute_parser: AttributeParser::new(tcx, tcx.features(), registered_tools),
}
}

Expand All @@ -196,6 +196,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}

struct SpanLowerer {
is_incremental: bool,
defid: LocalDefId,
}

impl SpanLowerer {
fn lower(&self, span: Span) -> Span {
if self.is_incremental {
span.with_parent(Some(self.defid))
} else {
// Do not make spans relative when not using incremental compilation.
span
}
}
}

#[extension(trait ResolverAstLoweringExt)]
impl ResolverAstLowering {
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>> {
Expand Down Expand Up @@ -739,15 +755,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
})
}

fn span_lowerer(&self) -> SpanLowerer {
SpanLowerer {
is_incremental: self.tcx.sess.opts.incremental.is_some(),
defid: self.current_hir_id_owner.def_id,
}
}

/// Intercept all spans entering HIR.
/// Mark a span as relative to the current owning item.
fn lower_span(&self, span: Span) -> Span {
if self.tcx.sess.opts.incremental.is_some() {
span.with_parent(Some(self.current_hir_id_owner.def_id))
} else {
// Do not make spans relative when not using incremental compilation.
span
}
self.span_lowerer().lower(span)
}

fn lower_ident(&self, ident: Ident) -> Ident {
Expand Down Expand Up @@ -870,7 +888,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
if attrs.is_empty() {
&[]
} else {
let lowered_attrs = self.lower_attrs_vec(attrs, self.lower_span(target_span));
let lowered_attrs = self.lower_attrs_vec(attrs, self.lower_span(target_span), id);

debug_assert_eq!(id.owner, self.current_hir_id_owner);
let ret = self.arena.alloc_from_iter(lowered_attrs);
Expand All @@ -890,9 +908,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}

fn lower_attrs_vec(&self, attrs: &[Attribute], target_span: Span) -> Vec<hir::Attribute> {
self.attribute_parser
.parse_attribute_list(attrs, target_span, OmitDoc::Lower, |s| self.lower_span(s))
fn lower_attrs_vec(
&mut self,
attrs: &[Attribute],
target_span: Span,
target_hir_id: HirId,
) -> Vec<hir::Attribute> {
let l = self.span_lowerer();
self.attribute_parser.parse_attribute_list(
attrs,
target_span,
target_hir_id,
OmitDoc::Lower,
|s| l.lower(s),
)
}

fn alias_attrs(&mut self, id: HirId, target_id: HirId) {
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_attr_data_structures/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use thin_vec::ThinVec;

use crate::{DefaultBodyStability, PartialConstStability, PrintAttribute, RustcVersion, Stability};

#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic, PrintAttribute)]
pub enum InlineAttr {
None,
Hint,
Expand Down Expand Up @@ -186,8 +186,10 @@ pub enum AttributeKind {
span: Span,
comment: Symbol,
},
Inline(InlineAttr, Span),
MacroTransparency(Transparency),
Repr(ThinVec<(ReprAttr, Span)>),
RustcForceInline(Span, Option<Symbol>),
Stability {
stability: Stability,
/// Span of the `#[stable(...)]` or `#[unstable(...)]` attribute
Expand Down
44 changes: 44 additions & 0 deletions compiler/rustc_attr_data_structures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,47 @@ print_tup!(A B C D E F G H);
print_skip!(Span, ());
print_disp!(Symbol, u16, bool, NonZero<u32>);
print_debug!(UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);

/// Finds attributes in sequences of attributes by pattern matching.
///
/// A little like `matches` but for attributes.
///
/// ```rust,ignore (illustrative)
/// // finds the repr attribute
/// if let Some(r) = find_attr!(attrs, AttributeKind::Repr(r) => r) {
///
/// }
///
/// // checks if one has matched
/// if find_attr!(attrs, AttributeKind::Repr(_)) {
///
/// }
/// ```
///
/// Often this requires you to first end up with a list of attributes.
/// A common way to get those is through `tcx.get_all_attrs(did)`
#[macro_export]
macro_rules! find_attr {
($attributes_list: expr, $pattern: pat $(if $guard: expr)?) => {{
$crate::find_attr!($attributes_list, $pattern $(if $guard)? => ()).is_some()
}};

($attributes_list: expr, $pattern: pat $(if $guard: expr)? => $e: expr) => {{
fn check_attribute_iterator<'a>(_: &'_ impl IntoIterator<Item = &'a rustc_hir::Attribute>) {}
check_attribute_iterator(&$attributes_list);

let find_attribute = |iter| {
for i in $attributes_list {
match i {
rustc_hir::Attribute::Parsed($pattern) $(if $guard)? => {
return Some($e);
}
_ => {}
}
}

None
};
find_attribute($attributes_list)
}};
}
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_hir = { path = "../rustc_hir" }
rustc_lexer = { path = "../rustc_lexer" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
Expand Down
18 changes: 13 additions & 5 deletions compiler/rustc_attr_parsing/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ attr_parsing_expects_feature_list =
attr_parsing_expects_features =
`{$name}` expects feature names

attr_parsing_incorrect_meta_item = expected a quoted string literal
attr_parsing_incorrect_meta_item_suggestion = consider surrounding this with quotes
attr_parsing_ill_formed_attribute_input = {$num_suggestions ->
[1] attribute must be of the form {$suggestions}
*[other] valid forms for the attribute are {$suggestions}
}

attr_parsing_incorrect_repr_format_align_one_arg =
incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
Expand Down Expand Up @@ -81,9 +83,6 @@ attr_parsing_missing_note =
attr_parsing_missing_since =
missing 'since'

attr_parsing_multiple_item =
multiple '{$item}' items

attr_parsing_multiple_stability_levels =
multiple stability levels

Expand Down Expand Up @@ -131,7 +130,16 @@ attr_parsing_unsupported_literal_generic =
attr_parsing_unsupported_literal_suggestion =
consider removing the prefix

attr_parsing_unused_duplicate =
unused attribute
.suggestion = remove this attribute
.note = attribute also specified here
.warn = {-passes_previously_accepted}

attr_parsing_unused_multiple =
multiple `{$name}` attributes
.suggestion = remove this attribute
.note = attribute also specified here

-attr_parsing_perviously_accepted =
this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
37 changes: 21 additions & 16 deletions compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs
Original file line number Diff line number Diff line change
@@ -1,44 +1,49 @@
use std::iter;

use rustc_attr_data_structures::AttributeKind;
use rustc_feature::{AttributeTemplate, template};
use rustc_span::{Span, Symbol, sym};

use super::{CombineAttributeParser, ConvertFn};
use crate::context::AcceptContext;
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
use crate::session_diagnostics;

pub(crate) struct AllowInternalUnstableParser;
impl CombineAttributeParser for AllowInternalUnstableParser {
impl<S: Stage> CombineAttributeParser<S> for AllowInternalUnstableParser {
const PATH: &'static [rustc_span::Symbol] = &[sym::allow_internal_unstable];
type Item = (Symbol, Span);
const CONVERT: ConvertFn<Self::Item> = AttributeKind::AllowInternalUnstable;
const TEMPLATE: AttributeTemplate = template!(Word, List: "feat1, feat2, ...");

fn extend<'a>(
cx: &'a AcceptContext<'a>,
args: &'a ArgParser<'a>,
) -> impl IntoIterator<Item = Self::Item> + 'a {
parse_unstable(cx, args, Self::PATH[0]).into_iter().zip(iter::repeat(cx.attr_span))
fn extend<'c>(
cx: &'c mut AcceptContext<'_, '_, S>,
args: &'c ArgParser<'_>,
) -> impl IntoIterator<Item = Self::Item> {
parse_unstable(cx, args, <Self as CombineAttributeParser<S>>::PATH[0])
.into_iter()
.zip(iter::repeat(cx.attr_span))
}
}

pub(crate) struct AllowConstFnUnstableParser;
impl CombineAttributeParser for AllowConstFnUnstableParser {
impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser {
const PATH: &'static [rustc_span::Symbol] = &[sym::rustc_allow_const_fn_unstable];
type Item = Symbol;
const CONVERT: ConvertFn<Self::Item> = AttributeKind::AllowConstFnUnstable;
const TEMPLATE: AttributeTemplate = template!(Word, List: "feat1, feat2, ...");

fn extend<'a>(
cx: &'a AcceptContext<'a>,
args: &'a ArgParser<'a>,
) -> impl IntoIterator<Item = Self::Item> + 'a {
parse_unstable(cx, args, Self::PATH[0])
fn extend<'c>(
cx: &'c mut AcceptContext<'_, '_, S>,
args: &'c ArgParser<'_>,
) -> impl IntoIterator<Item = Self::Item> + 'c {
parse_unstable(cx, args, <Self as CombineAttributeParser<S>>::PATH[0])
}
}

fn parse_unstable<'a>(
cx: &AcceptContext<'_>,
args: &'a ArgParser<'a>,
fn parse_unstable<S: Stage>(
cx: &AcceptContext<'_, '_, S>,
args: &ArgParser<'_>,
symbol: Symbol,
) -> impl IntoIterator<Item = Symbol> {
let mut res = Vec::new();
Expand Down
Loading
Loading