Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
3 changes: 3 additions & 0 deletions compiler/rustc_attr_data_structures/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@ pub enum AttributeKind {
/// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
Repr(ThinVec<(ReprAttr, Span)>),

/// Represents `#[rustc_skip_during_method_dispatch]`.
SkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span },

/// Represents `#[stable]`, `#[unstable]` and `#[rustc_allowed_through_unstable_modules]`.
Stability {
stability: Stability,
Expand Down
14 changes: 7 additions & 7 deletions compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ impl<S: Stage> SingleAttributeParser<S> for ColdParser {
const TEMPLATE: AttributeTemplate = template!(Word);

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
if !args.no_args() {
cx.expected_no_args(args.span().unwrap_or(cx.attr_span));
if let Err(span) = args.no_args() {
cx.expected_no_args(span);
return None;
}

Expand All @@ -67,8 +67,8 @@ pub(crate) struct NakedParser {
impl<S: Stage> AttributeParser<S> for NakedParser {
const ATTRIBUTES: AcceptMapping<Self, S> =
&[(&[sym::naked], template!(Word), |this, cx, args| {
if !args.no_args() {
cx.expected_no_args(args.span().unwrap_or(cx.attr_span));
if let Err(span) = args.no_args() {
cx.expected_no_args(span);
return;
}

Expand Down Expand Up @@ -175,10 +175,10 @@ impl<S: Stage> SingleAttributeParser<S> for NoMangleParser {
const TEMPLATE: AttributeTemplate = template!(Word);

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
if !args.no_args() {
cx.expected_no_args(args.span().unwrap_or(cx.attr_span));
if let Err(span) = args.no_args() {
cx.expected_no_args(span);
return None;
};
}

Some(AttributeKind::NoMangle(cx.attr_span))
}
Expand Down
12 changes: 8 additions & 4 deletions compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ impl<S: Stage> SingleAttributeParser<S> for AsPtrParser {
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(Word);

fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> {
// FIXME: check that there's no args (this is currently checked elsewhere)
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
if let Err(span) = args.no_args() {
cx.expected_no_args(span);
}
Some(AttributeKind::AsPtr(cx.attr_span))
}
}
Expand All @@ -27,8 +29,10 @@ impl<S: Stage> SingleAttributeParser<S> for PubTransparentParser {
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(Word);

fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> {
// FIXME: check that there's no args (this is currently checked elsewhere)
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
if let Err(span) = args.no_args() {
cx.expected_no_args(span);
}
Some(AttributeKind::PubTransparent(cx.attr_span))
}
}
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub(crate) mod must_use;
pub(crate) mod repr;
pub(crate) mod semantics;
pub(crate) mod stability;
pub(crate) mod traits;
pub(crate) mod transparency;
pub(crate) mod util;

Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_attr_parsing/src/attributes/semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ impl<S: Stage> SingleAttributeParser<S> for MayDangleParser {
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const TEMPLATE: AttributeTemplate = template!(Word);

fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> {
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
if let Err(span) = args.no_args() {
cx.expected_no_args(span);
}
Some(AttributeKind::MayDangle(cx.attr_span))
}
}
9 changes: 6 additions & 3 deletions compiler/rustc_attr_parsing/src/attributes/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,10 @@ impl<S: Stage> SingleAttributeParser<S> for ConstStabilityIndirectParser {
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
const TEMPLATE: AttributeTemplate = template!(Word);

fn convert(_cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> {
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
if let Err(span) = args.no_args() {
cx.expected_no_args(span);
}
Some(AttributeKind::ConstStabilityIndirect)
}
}
Expand Down Expand Up @@ -361,8 +364,8 @@ pub(crate) fn parse_unstability<S: Stage>(
};
}
Some(sym::soft) => {
if !param.args().no_args() {
cx.emit_err(session_diagnostics::SoftNoArgs { span: param.span() });
if let Err(span) = args.no_args() {
cx.emit_err(session_diagnostics::SoftNoArgs { span });
}
is_soft = true;
}
Expand Down
54 changes: 54 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use core::mem;

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

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

pub(crate) struct SkipDuringMethodDispatchParser;

impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser {
const PATH: &[Symbol] = &[sym::rustc_skip_during_method_dispatch];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;

const TEMPLATE: AttributeTemplate = template!(List: "array, boxed_slice");

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let mut array = false;
let mut boxed_slice = false;
let Some(args) = args.list() else {
cx.expected_list(cx.attr_span);
return None;
};
if args.is_empty() {
cx.expected_at_least_one_argument(args.span);
return None;
}
for arg in args.mixed() {
let Some(arg) = arg.meta_item() else {
cx.unexpected_literal(arg.span());
continue;
};
if let Err(span) = arg.args().no_args() {
cx.expected_no_args(span);
}
let path = arg.path();
let (key, skip): (Symbol, &mut bool) = match path.word_sym() {
Some(key @ sym::array) => (key, &mut array),
Some(key @ sym::boxed_slice) => (key, &mut boxed_slice),
_ => {
cx.expected_specific_argument(path.span(), vec!["array", "boxed_slice"]);
continue;
}
};
if mem::replace(skip, true) {
cx.duplicate_key(arg.span(), key);
}
}
Some(AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: cx.attr_span })
}
}
12 changes: 12 additions & 0 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use crate::attributes::semantics::MayDangleParser;
use crate::attributes::stability::{
BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
};
use crate::attributes::traits::SkipDuringMethodDispatchParser;
use crate::attributes::transparency::TransparencyParser;
use crate::attributes::{AttributeParser as _, Combine, Single};
use crate::parser::{ArgParser, MetaItemParser, PathParser};
Expand Down Expand Up @@ -119,6 +120,7 @@ attribute_parsers!(
Single<OptimizeParser>,
Single<PubTransparentParser>,
Single<RustcForceInlineParser>,
Single<SkipDuringMethodDispatchParser>,
Single<TransparencyParser>,
// tidy-alphabetical-end
];
Expand Down Expand Up @@ -325,6 +327,16 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
})
}

pub(crate) fn expected_at_least_one_argument(&self, span: Span) -> ErrorGuaranteed {
self.emit_err(AttributeParseError {
span,
attr_span: self.attr_span,
template: self.template.clone(),
attribute: self.attr_path.clone(),
reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
})
}

pub(crate) fn expected_specific_argument(
&self,
span: Span,
Expand Down
12 changes: 9 additions & 3 deletions compiler/rustc_attr_parsing/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,15 @@ impl<'a> ArgParser<'a> {
}
}

/// Asserts that there are no arguments
pub fn no_args(&self) -> bool {
matches!(self, Self::NoArgs)
/// Assert that there were no args.
/// If there were, get a span to the arguments
/// (to pass to [`AcceptContext::expected_no_args`](crate::context::AcceptContext::expected_no_args)).
pub fn no_args(&self) -> Result<(), Span> {
match self {
Self::NoArgs => Ok(()),
Self::List(args) => Err(args.span),
Self::NameValue(args) => Err(args.eq_span.to(args.value_span)),
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_attr_parsing/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,7 @@ pub(crate) struct NakedFunctionIncompatibleAttribute {
pub(crate) enum AttributeParseErrorReason {
ExpectedNoArgs,
ExpectedStringLiteral { byte_string: Option<Span> },
ExpectedAtLeastOneArgument,
ExpectedSingleArgument,
ExpectedList,
UnexpectedLiteral,
Expand Down Expand Up @@ -539,6 +540,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
diag.span_label(self.span, "expected a single argument here");
diag.code(E0805);
}
AttributeParseErrorReason::ExpectedAtLeastOneArgument => {
diag.span_label(self.span, "expected at least 1 argument here");
}
AttributeParseErrorReason::ExpectedList => {
diag.span_label(self.span, "expected this to be a list");
}
Expand Down
Loading
Loading