fix bugs in inline/force_inline and diagnostics of all attr parsers
This commit is contained in:
parent
566f691374
commit
ee976bbbca
34 changed files with 600 additions and 270 deletions
|
|
@ -235,8 +235,6 @@ pub enum AttributeKind {
|
|||
|
||||
/// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
|
||||
Repr(ThinVec<(ReprAttr, Span)>),
|
||||
/// Represents `#[rustc_force_inline]`
|
||||
RustcForceInline(Span, Option<Symbol>),
|
||||
/// Represents `#[stable]`, `#[unstable]` and `#[rustc_allowed_through_unstable_modules]`.
|
||||
Stability {
|
||||
stability: Stability,
|
||||
|
|
|
|||
|
|
@ -11,4 +11,5 @@ pub struct AttributeLint<Id> {
|
|||
#[derive(Clone, Debug, HashStable_Generic)]
|
||||
pub enum AttributeLintKind {
|
||||
UnusedDuplicate { this: Span, other: Span, warning: bool },
|
||||
IllFormedAttributeInput { suggestions: Vec<String> },
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@ attr_parsing_expects_feature_list =
|
|||
attr_parsing_expects_features =
|
||||
`{$name}` expects feature names
|
||||
|
||||
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_meta_item = expected a quoted string literal
|
||||
attr_parsing_incorrect_meta_item_suggestion = consider surrounding this with quotes
|
||||
|
||||
|
|
@ -136,6 +140,7 @@ attr_parsing_unused_duplicate =
|
|||
.suggestion = remove this attribute
|
||||
.note = attribute also specified here
|
||||
.warn = {-passes_previously_accepted}
|
||||
|
||||
attr_parsing_unused_multiple =
|
||||
multiple `{$name}` attributes
|
||||
.suggestion = remove this attribute
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use std::iter;
|
||||
|
||||
use rustc_attr_data_structures::AttributeKind;
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
||||
use super::{CombineAttributeParser, ConvertFn};
|
||||
|
|
@ -13,6 +14,7 @@ impl<S: Stage> CombineAttributeParser<S> for AllowInternalUnstableParser {
|
|||
const PATH: &[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<'c>(
|
||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||
|
|
@ -29,6 +31,7 @@ impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser {
|
|||
const PATH: &[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<'c>(
|
||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use rustc_attr_data_structures::AttributeKind;
|
||||
use rustc_feature::template;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
|
|
@ -13,37 +14,41 @@ pub(crate) struct ConfusablesParser {
|
|||
}
|
||||
|
||||
impl<S: Stage> AttributeParser<S> for ConfusablesParser {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> = &[(&[sym::rustc_confusables], |this, cx, args| {
|
||||
let Some(list) = args.list() else {
|
||||
// FIXME(jdonszelmann): error when not a list? Bring validation code here.
|
||||
// NOTE: currently subsequent attributes are silently ignored using
|
||||
// tcx.get_attr().
|
||||
return;
|
||||
};
|
||||
|
||||
if list.is_empty() {
|
||||
cx.emit_err(session_diagnostics::EmptyConfusables { span: cx.attr_span });
|
||||
}
|
||||
|
||||
for param in list.mixed() {
|
||||
let span = param.span();
|
||||
|
||||
let Some(lit) = param.lit() else {
|
||||
cx.emit_err(session_diagnostics::IncorrectMetaItem {
|
||||
span,
|
||||
suggestion: Some(session_diagnostics::IncorrectMetaItemSuggestion {
|
||||
lo: span.shrink_to_lo(),
|
||||
hi: span.shrink_to_hi(),
|
||||
}),
|
||||
});
|
||||
continue;
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
|
||||
&[sym::rustc_confusables],
|
||||
template!(List: r#""name1", "name2", ..."#),
|
||||
|this, cx, args| {
|
||||
let Some(list) = args.list() else {
|
||||
// FIXME(jdonszelmann): error when not a list? Bring validation code here.
|
||||
// NOTE: currently subsequent attributes are silently ignored using
|
||||
// tcx.get_attr().
|
||||
return;
|
||||
};
|
||||
|
||||
this.confusables.push(lit.symbol);
|
||||
}
|
||||
if list.is_empty() {
|
||||
cx.emit_err(session_diagnostics::EmptyConfusables { span: cx.attr_span });
|
||||
}
|
||||
|
||||
this.first_span.get_or_insert(cx.attr_span);
|
||||
})];
|
||||
for param in list.mixed() {
|
||||
let span = param.span();
|
||||
|
||||
let Some(lit) = param.lit() else {
|
||||
cx.emit_err(session_diagnostics::IncorrectMetaItem {
|
||||
span,
|
||||
suggestion: Some(session_diagnostics::IncorrectMetaItemSuggestion {
|
||||
lo: span.shrink_to_lo(),
|
||||
hi: span.shrink_to_hi(),
|
||||
}),
|
||||
});
|
||||
continue;
|
||||
};
|
||||
|
||||
this.confusables.push(lit.symbol);
|
||||
}
|
||||
|
||||
this.first_span.get_or_insert(cx.attr_span);
|
||||
},
|
||||
)];
|
||||
|
||||
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
if self.confusables.is_empty() {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use rustc_attr_data_structures::{AttributeKind, DeprecatedSince, Deprecation};
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
||||
use super::util::parse_version;
|
||||
|
|
@ -45,6 +46,11 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
|
|||
const PATH: &[Symbol] = &[sym::deprecated];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(
|
||||
Word,
|
||||
List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#,
|
||||
NameValueStr: "reason"
|
||||
);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let features = cx.features();
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ use super::{AcceptContext, AttributeOrder, OnDuplicate};
|
|||
use crate::attributes::SingleAttributeParser;
|
||||
use crate::context::Stage;
|
||||
use crate::parser::ArgParser;
|
||||
use crate::session_diagnostics::IncorrectMetaItem;
|
||||
|
||||
pub(crate) struct InlineParser;
|
||||
|
||||
|
|
@ -30,7 +29,7 @@ impl<S: Stage> SingleAttributeParser<S> for InlineParser {
|
|||
return None;
|
||||
};
|
||||
|
||||
match l.meta_item().and_then(|i| i.word_without_args().map(|i| i.name)) {
|
||||
match l.meta_item().and_then(|i| i.path().word().map(|i| i.name)) {
|
||||
Some(sym::always) => {
|
||||
Some(AttributeKind::Inline(InlineAttr::Always, cx.attr_span))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ use std::marker::PhantomData;
|
|||
|
||||
use rustc_attr_data_structures::AttributeKind;
|
||||
use rustc_attr_data_structures::lints::AttributeLintKind;
|
||||
use rustc_feature::AttributeTemplate;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
|
|
@ -37,7 +38,7 @@ pub(crate) mod transparency;
|
|||
pub(crate) mod util;
|
||||
|
||||
type AcceptFn<T, S> = for<'sess> fn(&mut T, &mut AcceptContext<'_, 'sess, S>, &ArgParser<'_>);
|
||||
type AcceptMapping<T, S> = &'static [(&'static [Symbol], AcceptFn<T, S>)];
|
||||
type AcceptMapping<T, S> = &'static [(&'static [Symbol], AttributeTemplate, AcceptFn<T, S>)];
|
||||
|
||||
/// An [`AttributeParser`] is a type which searches for syntactic attributes.
|
||||
///
|
||||
|
|
@ -89,6 +90,9 @@ pub(crate) trait SingleAttributeParser<S: Stage>: 'static {
|
|||
const ATTRIBUTE_ORDER: AttributeOrder;
|
||||
const ON_DUPLICATE: OnDuplicate<S>;
|
||||
|
||||
/// The template this attribute parser should implement. Used for diagnostics.
|
||||
const TEMPLATE: AttributeTemplate;
|
||||
|
||||
/// Converts a single syntactical attribute to a single semantic attribute, or [`AttributeKind`]
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind>;
|
||||
}
|
||||
|
|
@ -105,8 +109,10 @@ impl<T: SingleAttributeParser<S>, S: Stage> Default for Single<T, S> {
|
|||
}
|
||||
|
||||
impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S> {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> =
|
||||
&[(T::PATH, |group: &mut Single<T, S>, cx, args| {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
|
||||
T::PATH,
|
||||
<T as SingleAttributeParser<S>>::TEMPLATE,
|
||||
|group: &mut Single<T, S>, cx, args| {
|
||||
if let Some(pa) = T::convert(cx, args) {
|
||||
match T::ATTRIBUTE_ORDER {
|
||||
// keep the first and report immediately. ignore this attribute
|
||||
|
|
@ -127,7 +133,8 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
|
|||
|
||||
group.1 = Some((pa, cx.attr_span));
|
||||
}
|
||||
})];
|
||||
},
|
||||
)];
|
||||
|
||||
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
Some(self.1?.0)
|
||||
|
|
@ -224,6 +231,9 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
|
|||
type Item;
|
||||
const CONVERT: ConvertFn<Self::Item>;
|
||||
|
||||
/// The template this attribute parser should implement. Used for diagnostics.
|
||||
const TEMPLATE: AttributeTemplate;
|
||||
|
||||
/// Converts a single syntactical attribute to a number of elements of the semantic attribute, or [`AttributeKind`]
|
||||
fn extend<'c>(
|
||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||
|
|
@ -243,8 +253,11 @@ impl<T: CombineAttributeParser<S>, S: Stage> Default for Combine<T, S> {
|
|||
}
|
||||
|
||||
impl<T: CombineAttributeParser<S>, S: Stage> AttributeParser<S> for Combine<T, S> {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> =
|
||||
&[(T::PATH, |group: &mut Combine<T, S>, cx, args| group.1.extend(T::extend(cx, args)))];
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
|
||||
T::PATH,
|
||||
<T as CombineAttributeParser<S>>::TEMPLATE,
|
||||
|group: &mut Combine<T, S>, cx, args| group.1.extend(T::extend(cx, args)),
|
||||
)];
|
||||
|
||||
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
if self.1.is_empty() { None } else { Some(T::CONVERT(self.1)) }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use rustc_abi::Align;
|
||||
use rustc_ast::{IntTy, LitIntType, LitKind, UintTy};
|
||||
use rustc_attr_data_structures::{AttributeKind, IntType, ReprAttr};
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
|
||||
|
||||
use super::{CombineAttributeParser, ConvertFn};
|
||||
|
|
@ -23,6 +24,8 @@ impl<S: Stage> CombineAttributeParser<S> for ReprParser {
|
|||
type Item = (ReprAttr, Span);
|
||||
const PATH: &[Symbol] = &[sym::repr];
|
||||
const CONVERT: ConvertFn<Self::Item> = AttributeKind::Repr;
|
||||
// FIXME(jdonszelmann): never used
|
||||
const TEMPLATE: AttributeTemplate = template!(List: "C");
|
||||
|
||||
fn extend<'c>(
|
||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use rustc_attr_data_structures::{
|
|||
StableSince, UnstableReason, VERSION_PLACEHOLDER,
|
||||
};
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
||||
use super::util::parse_version;
|
||||
|
|
@ -43,26 +44,39 @@ impl StabilityParser {
|
|||
|
||||
impl<S: Stage> AttributeParser<S> for StabilityParser {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> = &[
|
||||
(&[sym::stable], |this, cx, args| {
|
||||
reject_outside_std!(cx);
|
||||
if !this.check_duplicate(cx)
|
||||
&& let Some((feature, level)) = parse_stability(cx, args)
|
||||
{
|
||||
this.stability = Some((Stability { level, feature }, cx.attr_span));
|
||||
}
|
||||
}),
|
||||
(&[sym::unstable], |this, cx, args| {
|
||||
reject_outside_std!(cx);
|
||||
if !this.check_duplicate(cx)
|
||||
&& let Some((feature, level)) = parse_unstability(cx, args)
|
||||
{
|
||||
this.stability = Some((Stability { level, feature }, cx.attr_span));
|
||||
}
|
||||
}),
|
||||
(&[sym::rustc_allowed_through_unstable_modules], |this, cx, args| {
|
||||
reject_outside_std!(cx);
|
||||
this.allowed_through_unstable_modules = args.name_value().and_then(|i| i.value_as_str())
|
||||
}),
|
||||
(
|
||||
&[sym::stable],
|
||||
template!(List: r#"feature = "name", since = "version""#),
|
||||
|this, cx, args| {
|
||||
reject_outside_std!(cx);
|
||||
if !this.check_duplicate(cx)
|
||||
&& let Some((feature, level)) = parse_stability(cx, args)
|
||||
{
|
||||
this.stability = Some((Stability { level, feature }, cx.attr_span));
|
||||
}
|
||||
},
|
||||
),
|
||||
(
|
||||
&[sym::unstable],
|
||||
template!(List: r#"feature = "name", reason = "...", issue = "N""#),
|
||||
|this, cx, args| {
|
||||
reject_outside_std!(cx);
|
||||
if !this.check_duplicate(cx)
|
||||
&& let Some((feature, level)) = parse_unstability(cx, args)
|
||||
{
|
||||
this.stability = Some((Stability { level, feature }, cx.attr_span));
|
||||
}
|
||||
},
|
||||
),
|
||||
(
|
||||
&[sym::rustc_allowed_through_unstable_modules],
|
||||
template!(NameValueStr: "deprecation message"),
|
||||
|this, cx, args| {
|
||||
reject_outside_std!(cx);
|
||||
this.allowed_through_unstable_modules =
|
||||
args.name_value().and_then(|i| i.value_as_str())
|
||||
},
|
||||
),
|
||||
];
|
||||
|
||||
fn finalize(mut self, cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
|
|
@ -96,8 +110,10 @@ pub(crate) struct BodyStabilityParser {
|
|||
}
|
||||
|
||||
impl<S: Stage> AttributeParser<S> for BodyStabilityParser {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> =
|
||||
&[(&[sym::rustc_default_body_unstable], |this, cx, args| {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
|
||||
&[sym::rustc_default_body_unstable],
|
||||
template!(List: r#"feature = "name", reason = "...", issue = "N""#),
|
||||
|this, cx, args| {
|
||||
reject_outside_std!(cx);
|
||||
if this.stability.is_some() {
|
||||
cx.dcx()
|
||||
|
|
@ -105,7 +121,8 @@ impl<S: Stage> AttributeParser<S> for BodyStabilityParser {
|
|||
} else if let Some((feature, level)) = parse_unstability(cx, args) {
|
||||
this.stability = Some((DefaultBodyStability { level, feature }, cx.attr_span));
|
||||
}
|
||||
})];
|
||||
},
|
||||
)];
|
||||
|
||||
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
let (stability, span) = self.stability?;
|
||||
|
|
@ -120,6 +137,7 @@ impl<S: Stage> SingleAttributeParser<S> for ConstStabilityIndirectParser {
|
|||
const PATH: &[Symbol] = &[sym::rustc_const_stable_indirect];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word);
|
||||
|
||||
fn convert(_cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
Some(AttributeKind::ConstStabilityIndirect)
|
||||
|
|
@ -146,7 +164,7 @@ impl ConstStabilityParser {
|
|||
|
||||
impl<S: Stage> AttributeParser<S> for ConstStabilityParser {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> = &[
|
||||
(&[sym::rustc_const_stable], |this, cx, args| {
|
||||
(&[sym::rustc_const_stable], template!(List: r#"feature = "name""#), |this, cx, args| {
|
||||
reject_outside_std!(cx);
|
||||
|
||||
if !this.check_duplicate(cx)
|
||||
|
|
@ -158,7 +176,7 @@ impl<S: Stage> AttributeParser<S> for ConstStabilityParser {
|
|||
));
|
||||
}
|
||||
}),
|
||||
(&[sym::rustc_const_unstable], |this, cx, args| {
|
||||
(&[sym::rustc_const_unstable], template!(List: r#"feature = "name""#), |this, cx, args| {
|
||||
reject_outside_std!(cx);
|
||||
if !this.check_duplicate(cx)
|
||||
&& let Some((feature, level)) = parse_unstability(cx, args)
|
||||
|
|
@ -169,7 +187,7 @@ impl<S: Stage> AttributeParser<S> for ConstStabilityParser {
|
|||
));
|
||||
}
|
||||
}),
|
||||
(&[sym::rustc_promotable], |this, cx, _| {
|
||||
(&[sym::rustc_promotable], template!(Word), |this, cx, _| {
|
||||
reject_outside_std!(cx);
|
||||
this.promotable = true;
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use rustc_attr_data_structures::AttributeKind;
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_span::hygiene::Transparency;
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
||||
|
|
@ -17,6 +18,8 @@ impl<S: Stage> SingleAttributeParser<S> for TransparencyParser {
|
|||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Custom(|cx, used, unused| {
|
||||
cx.dcx().span_err(vec![used, unused], "multiple macro transparency attributes");
|
||||
});
|
||||
const TEMPLATE: AttributeTemplate =
|
||||
template!(NameValueStr: "transparent|semitransparent|opaque");
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
match args.name_value().and_then(|nv| nv.value_as_str()) {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use rustc_ast::NodeId;
|
|||
use rustc_attr_data_structures::AttributeKind;
|
||||
use rustc_attr_data_structures::lints::{AttributeLint, AttributeLintKind};
|
||||
use rustc_errors::{DiagCtxtHandle, Diagnostic};
|
||||
use rustc_feature::Features;
|
||||
use rustc_feature::{AttributeTemplate, Features};
|
||||
use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, HirId};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
|
||||
|
|
@ -27,11 +27,12 @@ use crate::attributes::stability::{
|
|||
use crate::attributes::transparency::TransparencyParser;
|
||||
use crate::attributes::{AttributeParser as _, Combine, Single};
|
||||
use crate::parser::{ArgParser, MetaItemParser};
|
||||
use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason};
|
||||
|
||||
macro_rules! group_type {
|
||||
($stage: ty) => {
|
||||
LazyLock<(
|
||||
BTreeMap<&'static [Symbol], Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, $stage>, &ArgParser<'a>) + Send + Sync>>,
|
||||
BTreeMap<&'static [Symbol], Vec<(AttributeTemplate, Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, $stage>, &ArgParser<'a>) + Send + Sync>)>>,
|
||||
Vec<Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, $stage>) -> Option<AttributeKind>>>
|
||||
)>
|
||||
};
|
||||
|
|
@ -60,7 +61,7 @@ macro_rules! attribute_parsers {
|
|||
@[$ty: ty] pub(crate) static $name: ident = [$($names: ty),* $(,)?];
|
||||
) => {
|
||||
pub(crate) static $name: group_type!($ty) = LazyLock::new(|| {
|
||||
let mut accepts = BTreeMap::<_, Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, $ty>, &ArgParser<'a>) + Send + Sync>>::new();
|
||||
let mut accepts = BTreeMap::<_, Vec<(AttributeTemplate, Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, $ty>, &ArgParser<'a>) + Send + Sync>)>>::new();
|
||||
let mut finalizes = Vec::<Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, $ty>) -> Option<AttributeKind>>>::new();
|
||||
$(
|
||||
{
|
||||
|
|
@ -68,13 +69,12 @@ macro_rules! attribute_parsers {
|
|||
static STATE_OBJECT: RefCell<$names> = RefCell::new(<$names>::default());
|
||||
};
|
||||
|
||||
for (k, v) in <$names>::ATTRIBUTES {
|
||||
let old = accepts.insert(*k, Box::new(|cx, args| {
|
||||
for (path, template, accept_fn) in <$names>::ATTRIBUTES {
|
||||
accepts.entry(*path).or_default().push((*template, Box::new(|cx, args| {
|
||||
STATE_OBJECT.with_borrow_mut(|s| {
|
||||
v(s, cx, args)
|
||||
accept_fn(s, cx, args)
|
||||
})
|
||||
}));
|
||||
assert!(old.is_none());
|
||||
})));
|
||||
}
|
||||
|
||||
finalizes.push(Box::new(|cx| {
|
||||
|
|
@ -168,6 +168,14 @@ pub(crate) struct AcceptContext<'f, 'sess, S: Stage> {
|
|||
pub(crate) finalize_cx: FinalizeContext<'f, 'sess, S>,
|
||||
/// The span of the attribute currently being parsed
|
||||
pub(crate) attr_span: Span,
|
||||
|
||||
/// The expected structure of the attribute.
|
||||
///
|
||||
/// Used in reporting errors to give a hint to users what the attribute *should* look like.
|
||||
pub(crate) template: &'f AttributeTemplate,
|
||||
|
||||
/// The name of the attribute we're currently accepting.
|
||||
pub(crate) attr_path: AttrPath,
|
||||
}
|
||||
|
||||
impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
||||
|
|
@ -175,10 +183,54 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
S::emit_err(&self.sess, diag)
|
||||
}
|
||||
|
||||
/// Emit a lint. This method is somewhat special, since lints emitted during attribute parsing
|
||||
/// must be delayed until after HIR is built. This method will take care of the details of
|
||||
/// that.
|
||||
pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
|
||||
let id = self.target_id;
|
||||
(self.emit_lint)(AttributeLint { id, span, kind: lint });
|
||||
}
|
||||
|
||||
pub(crate) fn expected_string_literal(&self, span: Span) -> ErrorGuaranteed {
|
||||
// 539?
|
||||
self.emit_err(AttributeParseError {
|
||||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
reason: AttributeParseErrorReason::ExpectedStringLiteral,
|
||||
})
|
||||
}
|
||||
|
||||
// pub(crate) fn expected_any_arguments(&self, span: Span) -> ErrorGuaranteed {
|
||||
//
|
||||
// }
|
||||
|
||||
pub(crate) fn expected_single_argument(&self, span: Span) -> ErrorGuaranteed {
|
||||
// E534?
|
||||
self.emit_err(AttributeParseError {
|
||||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
reason: AttributeParseErrorReason::ExpectedSingleArgument,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn expected_specific_argument(
|
||||
&self,
|
||||
span: Span,
|
||||
options: Vec<&'static str>,
|
||||
) -> ErrorGuaranteed {
|
||||
// E535?
|
||||
self.emit_err(AttributeParseError {
|
||||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
reason: AttributeParseErrorReason::ExpectedSpecificArgument(options),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> {
|
||||
|
|
@ -377,18 +429,22 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
let args = parser.args();
|
||||
let parts = path.segments().map(|i| i.name).collect::<Vec<_>>();
|
||||
|
||||
if let Some(accept) = S::parsers().0.get(parts.as_slice()) {
|
||||
let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext {
|
||||
finalize_cx: FinalizeContext {
|
||||
cx: self,
|
||||
target_span,
|
||||
target_id,
|
||||
emit_lint: &mut emit_lint,
|
||||
},
|
||||
attr_span: lower_span(attr.span),
|
||||
};
|
||||
if let Some(accepts) = S::parsers().0.get(parts.as_slice()) {
|
||||
for (template, accept) in accepts {
|
||||
let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext {
|
||||
finalize_cx: FinalizeContext {
|
||||
cx: self,
|
||||
target_span,
|
||||
target_id,
|
||||
emit_lint: &mut emit_lint,
|
||||
},
|
||||
attr_span: lower_span(attr.span),
|
||||
template,
|
||||
attr_path: path.get_attribute_path(),
|
||||
};
|
||||
|
||||
accept(&mut cx, args)
|
||||
accept(&mut cx, args)
|
||||
}
|
||||
} else {
|
||||
// If we're here, we must be compiling a tool attribute... Or someone
|
||||
// forgot to parse their fancy new attribute. Let's warn them in any case.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use rustc_attr_data_structures::lints::{AttributeLint, AttributeLintKind};
|
||||
use rustc_errors::LintEmitter;
|
||||
use rustc_errors::{DiagArgValue, LintEmitter};
|
||||
use rustc_hir::HirId;
|
||||
|
||||
use crate::session_diagnostics;
|
||||
|
|
@ -15,5 +15,18 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emi
|
|||
*span,
|
||||
session_diagnostics::UnusedDuplicate { this, other, warning },
|
||||
),
|
||||
AttributeLintKind::IllFormedAttributeInput { suggestions } => {
|
||||
lint_emitter.emit_node_span_lint(
|
||||
rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT,
|
||||
*id,
|
||||
*span,
|
||||
session_diagnostics::IllFormedAttributeInput {
|
||||
num_suggestions: suggestions.len(),
|
||||
suggestions: DiagArgValue::StrListSepByAnd(
|
||||
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@ use std::num::IntErrorKind;
|
|||
|
||||
use rustc_ast as ast;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level};
|
||||
use rustc_errors::{
|
||||
Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
|
||||
};
|
||||
use rustc_feature::AttributeTemplate;
|
||||
use rustc_hir::AttrPath;
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
||||
|
|
@ -462,6 +466,14 @@ pub(crate) struct UnusedDuplicate {
|
|||
pub warning: bool,
|
||||
}
|
||||
|
||||
// FIXME(jdonszelmann): duplicated in rustc_lints, should be moved here completely.
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(attr_parsing_ill_formed_attribute_input)]
|
||||
pub(crate) struct IllFormedAttributeInput {
|
||||
pub num_suggestions: usize,
|
||||
pub suggestions: DiagArgValue,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_stability_outside_std, code = E0734)]
|
||||
pub(crate) struct StabilityOutsideStd {
|
||||
|
|
@ -490,3 +502,72 @@ pub(crate) struct UnrecognizedReprHint {
|
|||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
pub(crate) enum AttributeParseErrorReason {
|
||||
ExpectedStringLiteral,
|
||||
ExpectedSingleArgument,
|
||||
ExpectedSpecificArgument(Vec<&'static str>),
|
||||
}
|
||||
|
||||
pub(crate) struct AttributeParseError {
|
||||
pub(crate) span: Span,
|
||||
pub(crate) attr_span: Span,
|
||||
pub(crate) template: AttributeTemplate,
|
||||
pub(crate) attribute: AttrPath,
|
||||
pub(crate) reason: AttributeParseErrorReason,
|
||||
}
|
||||
|
||||
impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
|
||||
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
|
||||
let name = self.attribute.to_string();
|
||||
|
||||
let mut diag = Diag::new(dcx, level, format!("malformed `{name}` attribute input"));
|
||||
diag.span(self.attr_span);
|
||||
diag.code(E0539);
|
||||
match self.reason {
|
||||
AttributeParseErrorReason::ExpectedStringLiteral => {
|
||||
diag.span_note(self.span, "expected a string literal here");
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedSingleArgument => {
|
||||
diag.span_note(self.span, "expected a single argument here");
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedSpecificArgument(possibilities) => {
|
||||
match possibilities.as_slice() {
|
||||
&[] => {}
|
||||
&[x] => {
|
||||
diag.span_note(self.span, format!("the only valid argument here is `{x}`"));
|
||||
}
|
||||
[first, second] => {
|
||||
diag.span_note(
|
||||
self.span,
|
||||
format!("valid arguments are `{first}` or `{second}`"),
|
||||
);
|
||||
}
|
||||
[first @ .., second_to_last, last] => {
|
||||
let mut res = String::new();
|
||||
for i in first {
|
||||
res.push_str(&format!("`{i}`, "));
|
||||
}
|
||||
res.push_str(&format!("`{second_to_last}` or `{last}`"));
|
||||
|
||||
diag.span_note(self.span, format!("valid arguments are {res}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let suggestions = self.template.suggestions(false, &name);
|
||||
diag.span_suggestions(
|
||||
self.attr_span,
|
||||
if suggestions.len() == 1 {
|
||||
"must be of the form"
|
||||
} else {
|
||||
"the following are possible correct uses"
|
||||
},
|
||||
suggestions,
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_ast::expand::autodiff_attrs::{
|
||||
AutoDiffAttrs, DiffActivity, DiffMode, valid_input_activity, valid_ret_activity,
|
||||
};
|
||||
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
|
||||
use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr};
|
||||
use rustc_attr_data_structures::ReprAttr::ReprAlign;
|
||||
use rustc_attr_data_structures::{
|
||||
|
|
@ -86,7 +84,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
|
||||
let rust_target_features = tcx.rust_target_features(LOCAL_CRATE);
|
||||
|
||||
let mut inline_span = None;
|
||||
let mut link_ordinal_span = None;
|
||||
let mut no_sanitize_span = None;
|
||||
let mut mixed_export_name_no_mangle_lint_state = MixedExportNameAndNoMangleState::default();
|
||||
|
|
@ -452,8 +449,14 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
|
||||
mixed_export_name_no_mangle_lint_state.lint_if_mixed(tcx);
|
||||
|
||||
codegen_fn_attrs.inline =
|
||||
find_attr!(attrs, AttributeKind::Inline(i, _) => *i).unwrap_or(InlineAttr::None);
|
||||
let inline_span;
|
||||
(codegen_fn_attrs.inline, inline_span) = if let Some((inline_attr, span)) =
|
||||
find_attr!(attrs, AttributeKind::Inline(i, span) => (*i, *span))
|
||||
{
|
||||
(inline_attr, Some(span))
|
||||
} else {
|
||||
(InlineAttr::None, None)
|
||||
};
|
||||
|
||||
// naked function MUST NOT be inlined! This attribute is required for the rust compiler itself,
|
||||
// but not for the code generation backend because at that point the naked function will just be
|
||||
|
|
@ -474,7 +477,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
return OptimizeAttr::Default;
|
||||
};
|
||||
|
||||
inline_span = Some(attr.span());
|
||||
let [item] = &items[..] else {
|
||||
tcx.dcx().emit_err(errors::ExpectedOneArgumentOptimize { span: attr.span() });
|
||||
return OptimizeAttr::Default;
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ pub enum AttributeGate {
|
|||
Ungated,
|
||||
}
|
||||
|
||||
// FIXME(jdonszelmann): move to rustc_attr_data_structures
|
||||
/// A template that the attribute input must match.
|
||||
/// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now.
|
||||
#[derive(Clone, Copy, Default)]
|
||||
|
|
@ -127,6 +128,26 @@ pub struct AttributeTemplate {
|
|||
pub name_value_str: Option<&'static str>,
|
||||
}
|
||||
|
||||
impl AttributeTemplate {
|
||||
pub fn suggestions(&self, inner: bool, name: impl std::fmt::Display) -> Vec<String> {
|
||||
let mut suggestions = vec![];
|
||||
let inner = if inner { "!" } else { "" };
|
||||
if self.word {
|
||||
suggestions.push(format!("#{inner}[{name}]"));
|
||||
}
|
||||
if let Some(descr) = self.list {
|
||||
suggestions.push(format!("#{inner}[{name}({descr})]"));
|
||||
}
|
||||
suggestions.extend(self.one_of.iter().map(|&word| format!("#{inner}[{name}({word})]")));
|
||||
if let Some(descr) = self.name_value_str {
|
||||
suggestions.push(format!("#{inner}[{name} = \"{descr}\"]"));
|
||||
}
|
||||
suggestions.sort();
|
||||
|
||||
suggestions
|
||||
}
|
||||
}
|
||||
|
||||
/// How to handle multiple duplicate attributes on the same item.
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub enum AttributeDuplicates {
|
||||
|
|
@ -181,20 +202,21 @@ pub enum AttributeDuplicates {
|
|||
/// A convenience macro for constructing attribute templates.
|
||||
/// E.g., `template!(Word, List: "description")` means that the attribute
|
||||
/// supports forms `#[attr]` and `#[attr(description)]`.
|
||||
#[macro_export]
|
||||
macro_rules! template {
|
||||
(Word) => { template!(@ true, None, &[], None) };
|
||||
(List: $descr: expr) => { template!(@ false, Some($descr), &[], None) };
|
||||
(OneOf: $one_of: expr) => { template!(@ false, None, $one_of, None) };
|
||||
(NameValueStr: $descr: expr) => { template!(@ false, None, &[], Some($descr)) };
|
||||
(Word, List: $descr: expr) => { template!(@ true, Some($descr), &[], None) };
|
||||
(Word, NameValueStr: $descr: expr) => { template!(@ true, None, &[], Some($descr)) };
|
||||
(Word) => { $crate::template!(@ true, None, &[], None) };
|
||||
(List: $descr: expr) => { $crate::template!(@ false, Some($descr), &[], None) };
|
||||
(OneOf: $one_of: expr) => { $crate::template!(@ false, None, $one_of, None) };
|
||||
(NameValueStr: $descr: expr) => { $crate::template!(@ false, None, &[], Some($descr)) };
|
||||
(Word, List: $descr: expr) => { $crate::template!(@ true, Some($descr), &[], None) };
|
||||
(Word, NameValueStr: $descr: expr) => { $crate::template!(@ true, None, &[], Some($descr)) };
|
||||
(List: $descr1: expr, NameValueStr: $descr2: expr) => {
|
||||
template!(@ false, Some($descr1), &[], Some($descr2))
|
||||
$crate::template!(@ false, Some($descr1), &[], Some($descr2))
|
||||
};
|
||||
(Word, List: $descr1: expr, NameValueStr: $descr2: expr) => {
|
||||
template!(@ true, Some($descr1), &[], Some($descr2))
|
||||
$crate::template!(@ true, Some($descr1), &[], Some($descr2))
|
||||
};
|
||||
(@ $word: expr, $list: expr, $one_of: expr, $name_value_str: expr) => { AttributeTemplate {
|
||||
(@ $word: expr, $list: expr, $one_of: expr, $name_value_str: expr) => { $crate::AttributeTemplate {
|
||||
word: $word, list: $list, one_of: $one_of, name_value_str: $name_value_str
|
||||
} };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2618,6 +2618,7 @@ pub(crate) struct UnusedCrateDependency {
|
|||
pub local_crate: Symbol,
|
||||
}
|
||||
|
||||
// FIXME(jdonszelmann): duplicated in rustc_attr_parsing, should be moved there completely.
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_ill_formed_attribute_input)]
|
||||
pub(crate) struct IllFormedAttributeInput {
|
||||
|
|
|
|||
|
|
@ -282,11 +282,15 @@ fn emit_malformed_attribute(
|
|||
name: Symbol,
|
||||
template: AttributeTemplate,
|
||||
) {
|
||||
// attrs with new parsers are locally validated so excluded here
|
||||
if matches!(name, sym::inline | sym::rustc_force_inline) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Some of previously accepted forms were used in practice,
|
||||
// report them as warnings for now.
|
||||
let should_warn = |name| {
|
||||
matches!(name, sym::doc | sym::ignore | sym::inline | sym::link | sym::test | sym::bench)
|
||||
};
|
||||
let should_warn =
|
||||
|name| matches!(name, sym::doc | sym::ignore | sym::link | sym::test | sym::bench);
|
||||
|
||||
let error_msg = format!("malformed `{name}` attribute input");
|
||||
let mut suggestions = vec![];
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
AttributeKind::Stability { span, .. }
|
||||
| AttributeKind::ConstStability { span, .. },
|
||||
) => self.check_stability_promotable(*span, target),
|
||||
Attribute::Parsed(AttributeKind::Inline(InlineAttr::Force { .. }, ..)) => {} // handled separately below
|
||||
Attribute::Parsed(AttributeKind::Inline(kind, attr_span)) => {
|
||||
self.check_inline(hir_id, *attr_span, span, kind, target)
|
||||
}
|
||||
|
|
@ -682,6 +683,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
) => {
|
||||
continue;
|
||||
}
|
||||
Attribute::Parsed(AttributeKind::Inline(.., span)) => {
|
||||
self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute {
|
||||
span: *span,
|
||||
naked_span: attr.span(),
|
||||
attr: sym::inline.to_string(),
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
// FIXME(jdonszelmann): make exhaustive
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
|
@ -2902,7 +2913,8 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
|
|||
fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>) {
|
||||
let attrs = tcx.hir_attrs(item.hir_id());
|
||||
|
||||
if let Some(attr_span) = find_attr!(attrs, AttributeKind::Inline(_, span) => *span) {
|
||||
if let Some(attr_span) = find_attr!(attrs, AttributeKind::Inline(i, span) if !matches!(i, InlineAttr::Force{..}) => *span)
|
||||
{
|
||||
tcx.dcx().emit_err(errors::NonExportedMacroInvalidAttrs { attr_span });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
error[E0518]: attribute should be applied to function or closure
|
||||
--> $DIR/multiple-invalid.rs:4:1
|
||||
|
|
||||
LL | #[inline]
|
||||
| ^^^^^^^^^
|
||||
...
|
||||
LL | const FOO: u8 = 0;
|
||||
| ------------------ not a function or closure
|
||||
|
||||
error: attribute should be applied to a function definition
|
||||
--> $DIR/multiple-invalid.rs:6:1
|
||||
|
|
||||
|
|
@ -16,6 +7,15 @@ LL |
|
|||
LL | const FOO: u8 = 0;
|
||||
| ------------------ not a function definition
|
||||
|
||||
error[E0518]: attribute should be applied to function or closure
|
||||
--> $DIR/multiple-invalid.rs:4:1
|
||||
|
|
||||
LL | #[inline]
|
||||
| ^^^^^^^^^
|
||||
...
|
||||
LL | const FOO: u8 = 0;
|
||||
| ------------------ not a function or closure
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0518`.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#[inline()] //~ ERROR E0534
|
||||
#[inline()] //~ ERROR malformed `inline` attribute input
|
||||
pub fn something() {}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,22 @@
|
|||
error[E0534]: expected one argument
|
||||
error[E0539]: malformed `inline` attribute input
|
||||
--> $DIR/E0534.rs:1:1
|
||||
|
|
||||
LL | #[inline()]
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
note: expected a single argument here
|
||||
--> $DIR/E0534.rs:1:9
|
||||
|
|
||||
LL | #[inline()]
|
||||
| ^^
|
||||
help: the following are possible correct uses
|
||||
|
|
||||
LL | #[inline(always|never)]
|
||||
| ++++++++++++
|
||||
LL - #[inline()]
|
||||
LL + #[inline]
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0534`.
|
||||
For more information about this error, try `rustc --explain E0539`.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ LL | #![rustc_main]
|
|||
= note: the `#[rustc_main]` attribute is an internal implementation detail that will never be stable
|
||||
= note: the `#[rustc_main]` attribute is used internally to specify test entry point function
|
||||
|
||||
error: valid forms for the attribute are `#[inline]` and `#[inline(always|never)]`
|
||||
error: valid forms for the attribute are `#[inline(always|never)]` and `#[inline]`
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5
|
||||
|
|
||||
LL | #[inline = "2100"] fn f() { }
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
// Test that invalid force inlining attributes error as expected.
|
||||
|
||||
#[rustc_force_inline("foo")]
|
||||
//~^ ERROR malformed `rustc_force_inline` attribute input
|
||||
pub fn forced1() {
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,71 +1,80 @@
|
|||
error: malformed `rustc_force_inline` attribute input
|
||||
--> $DIR/invalid.rs:11:1
|
||||
|
|
||||
LL | #[rustc_force_inline("foo")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: the following are the possible correct uses
|
||||
|
|
||||
LL - #[rustc_force_inline("foo")]
|
||||
LL + #[rustc_force_inline = "reason"]
|
||||
|
|
||||
LL - #[rustc_force_inline("foo")]
|
||||
LL + #[rustc_force_inline]
|
||||
|
|
||||
|
||||
error: malformed `rustc_force_inline` attribute input
|
||||
--> $DIR/invalid.rs:16:1
|
||||
|
|
||||
LL | #[rustc_force_inline(bar, baz)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: the following are the possible correct uses
|
||||
|
|
||||
LL - #[rustc_force_inline(bar, baz)]
|
||||
LL + #[rustc_force_inline = "reason"]
|
||||
|
|
||||
LL - #[rustc_force_inline(bar, baz)]
|
||||
LL + #[rustc_force_inline]
|
||||
|
|
||||
|
||||
error: malformed `rustc_force_inline` attribute input
|
||||
--> $DIR/invalid.rs:21:1
|
||||
|
|
||||
LL | #[rustc_force_inline(2)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: the following are the possible correct uses
|
||||
|
|
||||
LL - #[rustc_force_inline(2)]
|
||||
LL + #[rustc_force_inline = "reason"]
|
||||
|
|
||||
LL - #[rustc_force_inline(2)]
|
||||
LL + #[rustc_force_inline]
|
||||
|
|
||||
|
||||
error: malformed `rustc_force_inline` attribute input
|
||||
--> $DIR/invalid.rs:26:1
|
||||
|
|
||||
LL | #[rustc_force_inline = 2]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: the following are the possible correct uses
|
||||
|
|
||||
LL - #[rustc_force_inline = 2]
|
||||
LL + #[rustc_force_inline = "reason"]
|
||||
|
|
||||
LL - #[rustc_force_inline = 2]
|
||||
LL + #[rustc_force_inline]
|
||||
|
|
||||
|
||||
error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
|
||||
--> $DIR/invalid.rs:133:11
|
||||
--> $DIR/invalid.rs:132:11
|
||||
|
|
||||
LL | fn barqux(#[rustc_force_inline] _x: u32) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0539]: malformed `rustc_force_inline` attribute input
|
||||
--> $DIR/invalid.rs:15:1
|
||||
|
|
||||
LL | #[rustc_force_inline(bar, baz)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: expected a single argument here
|
||||
--> $DIR/invalid.rs:15:21
|
||||
|
|
||||
LL | #[rustc_force_inline(bar, baz)]
|
||||
| ^^^^^^^^^^
|
||||
help: the following are possible correct uses
|
||||
|
|
||||
LL - #[rustc_force_inline(bar, baz)]
|
||||
LL + #[rustc_force_inline = "reason"]
|
||||
|
|
||||
LL - #[rustc_force_inline(bar, baz)]
|
||||
LL + #[rustc_force_inline(reason)]
|
||||
|
|
||||
LL - #[rustc_force_inline(bar, baz)]
|
||||
LL + #[rustc_force_inline]
|
||||
|
|
||||
|
||||
error[E0539]: malformed `rustc_force_inline` attribute input
|
||||
--> $DIR/invalid.rs:20:1
|
||||
|
|
||||
LL | #[rustc_force_inline(2)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: expected a string literal here
|
||||
--> $DIR/invalid.rs:20:22
|
||||
|
|
||||
LL | #[rustc_force_inline(2)]
|
||||
| ^
|
||||
help: the following are possible correct uses
|
||||
|
|
||||
LL - #[rustc_force_inline(2)]
|
||||
LL + #[rustc_force_inline = "reason"]
|
||||
|
|
||||
LL - #[rustc_force_inline(2)]
|
||||
LL + #[rustc_force_inline(reason)]
|
||||
|
|
||||
LL - #[rustc_force_inline(2)]
|
||||
LL + #[rustc_force_inline]
|
||||
|
|
||||
|
||||
error[E0539]: malformed `rustc_force_inline` attribute input
|
||||
--> $DIR/invalid.rs:25:1
|
||||
|
|
||||
LL | #[rustc_force_inline = 2]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: expected a string literal here
|
||||
--> $DIR/invalid.rs:25:24
|
||||
|
|
||||
LL | #[rustc_force_inline = 2]
|
||||
| ^
|
||||
help: the following are possible correct uses
|
||||
|
|
||||
LL - #[rustc_force_inline = 2]
|
||||
LL + #[rustc_force_inline = "reason"]
|
||||
|
|
||||
LL - #[rustc_force_inline = 2]
|
||||
LL + #[rustc_force_inline(reason)]
|
||||
|
|
||||
LL - #[rustc_force_inline = 2]
|
||||
LL + #[rustc_force_inline]
|
||||
|
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:31:1
|
||||
--> $DIR/invalid.rs:30:1
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -74,7 +83,7 @@ LL | extern crate std as other_std;
|
|||
| ------------------------------ not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:35:1
|
||||
--> $DIR/invalid.rs:34:1
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -83,7 +92,7 @@ LL | use std::collections::HashMap;
|
|||
| ------------------------------ not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:39:1
|
||||
--> $DIR/invalid.rs:38:1
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -92,7 +101,7 @@ LL | static _FOO: &'static str = "FOO";
|
|||
| ---------------------------------- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:43:1
|
||||
--> $DIR/invalid.rs:42:1
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -101,7 +110,7 @@ LL | const _BAR: u32 = 3;
|
|||
| -------------------- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:47:1
|
||||
--> $DIR/invalid.rs:46:1
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -110,7 +119,7 @@ LL | mod foo { }
|
|||
| ----------- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:51:1
|
||||
--> $DIR/invalid.rs:50:1
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -125,7 +134,7 @@ LL | | }
|
|||
| |_- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:67:1
|
||||
--> $DIR/invalid.rs:66:1
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -134,7 +143,7 @@ LL | type Foo = u32;
|
|||
| --------------- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:71:1
|
||||
--> $DIR/invalid.rs:70:1
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -147,13 +156,13 @@ LL | | }
|
|||
| |_- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:73:10
|
||||
--> $DIR/invalid.rs:72:10
|
||||
|
|
||||
LL | enum Bar<#[rustc_force_inline] T> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ - not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:75:5
|
||||
--> $DIR/invalid.rs:74:5
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -162,7 +171,7 @@ LL | Baz(std::marker::PhantomData<T>),
|
|||
| -------------------------------- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:80:1
|
||||
--> $DIR/invalid.rs:79:1
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -175,7 +184,7 @@ LL | | }
|
|||
| |_- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:83:5
|
||||
--> $DIR/invalid.rs:82:5
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -184,7 +193,7 @@ LL | field: u32,
|
|||
| ---------- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:88:1
|
||||
--> $DIR/invalid.rs:87:1
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -196,7 +205,7 @@ LL | | }
|
|||
| |_- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:95:1
|
||||
--> $DIR/invalid.rs:94:1
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -211,7 +220,7 @@ LL | | }
|
|||
| |_- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:110:1
|
||||
--> $DIR/invalid.rs:109:1
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -220,7 +229,7 @@ LL | trait FooQux = FooBaz;
|
|||
| ---------------------- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:114:1
|
||||
--> $DIR/invalid.rs:113:1
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -233,7 +242,7 @@ LL | | }
|
|||
| |_- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:122:1
|
||||
--> $DIR/invalid.rs:121:1
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -245,7 +254,7 @@ LL | | }
|
|||
| |_- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:129:1
|
||||
--> $DIR/invalid.rs:128:1
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -254,7 +263,7 @@ LL | macro_rules! barqux { ($foo:tt) => { $foo }; }
|
|||
| ---------------------------------------------- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:133:11
|
||||
--> $DIR/invalid.rs:132:11
|
||||
|
|
||||
LL | fn barqux(#[rustc_force_inline] _x: u32) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^--------
|
||||
|
|
@ -262,7 +271,7 @@ LL | fn barqux(#[rustc_force_inline] _x: u32) {}
|
|||
| not a function definition
|
||||
|
||||
error: attribute cannot be applied to a `async`, `gen` or `async gen` function
|
||||
--> $DIR/invalid.rs:137:1
|
||||
--> $DIR/invalid.rs:136:1
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -271,7 +280,7 @@ LL | async fn async_foo() {}
|
|||
| -------------------- `async`, `gen` or `async gen` function
|
||||
|
||||
error: attribute cannot be applied to a `async`, `gen` or `async gen` function
|
||||
--> $DIR/invalid.rs:141:1
|
||||
--> $DIR/invalid.rs:140:1
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -280,7 +289,7 @@ LL | gen fn gen_foo() {}
|
|||
| ---------------- `async`, `gen` or `async gen` function
|
||||
|
||||
error: attribute cannot be applied to a `async`, `gen` or `async gen` function
|
||||
--> $DIR/invalid.rs:145:1
|
||||
--> $DIR/invalid.rs:144:1
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -289,19 +298,19 @@ LL | async gen fn async_gen_foo() {}
|
|||
| ---------------------------- `async`, `gen` or `async gen` function
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:150:14
|
||||
--> $DIR/invalid.rs:149:14
|
||||
|
|
||||
LL | let _x = #[rustc_force_inline] || { };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ ------ not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:152:14
|
||||
--> $DIR/invalid.rs:151:14
|
||||
|
|
||||
LL | let _y = #[rustc_force_inline] 3 + 4;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ - not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:154:5
|
||||
--> $DIR/invalid.rs:153:5
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -310,7 +319,7 @@ LL | let _z = 3;
|
|||
| ----------- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:159:9
|
||||
--> $DIR/invalid.rs:158:9
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -319,7 +328,7 @@ LL | 1 => (),
|
|||
| ------- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:98:5
|
||||
--> $DIR/invalid.rs:97:5
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -328,7 +337,7 @@ LL | type Foo;
|
|||
| --------- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:101:5
|
||||
--> $DIR/invalid.rs:100:5
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -337,7 +346,7 @@ LL | const Bar: i32;
|
|||
| --------------- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:105:5
|
||||
--> $DIR/invalid.rs:104:5
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -346,7 +355,7 @@ LL | fn foo() {}
|
|||
| ----------- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:117:5
|
||||
--> $DIR/invalid.rs:116:5
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -355,7 +364,7 @@ LL | fn foo() {}
|
|||
| ----------- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:54:5
|
||||
--> $DIR/invalid.rs:53:5
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -364,7 +373,7 @@ LL | static X: &'static u32;
|
|||
| ----------------------- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:58:5
|
||||
--> $DIR/invalid.rs:57:5
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -373,7 +382,7 @@ LL | type Y;
|
|||
| ------- not a function definition
|
||||
|
||||
error: attribute should be applied to a function
|
||||
--> $DIR/invalid.rs:62:5
|
||||
--> $DIR/invalid.rs:61:5
|
||||
|
|
||||
LL | #[rustc_force_inline]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -381,5 +390,6 @@ LL |
|
|||
LL | fn foo();
|
||||
| --------- not a function definition
|
||||
|
||||
error: aborting due to 38 previous errors
|
||||
error: aborting due to 37 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0539`.
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
#[inline(please,no)] //~ ERROR expected one argument
|
||||
#[inline(please,no)] //~ ERROR malformed `inline` attribute
|
||||
fn a() {
|
||||
}
|
||||
|
||||
#[inline()] //~ ERROR expected one argument
|
||||
#[inline()] //~ ERROR malformed `inline` attribute
|
||||
fn b() {
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,42 @@
|
|||
error[E0534]: expected one argument
|
||||
error[E0539]: malformed `inline` attribute input
|
||||
--> $DIR/invalid-inline.rs:3:1
|
||||
|
|
||||
LL | #[inline(please,no)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: expected a single argument here
|
||||
--> $DIR/invalid-inline.rs:3:9
|
||||
|
|
||||
LL | #[inline(please,no)]
|
||||
| ^^^^^^^^^^^
|
||||
help: the following are possible correct uses
|
||||
|
|
||||
LL - #[inline(please,no)]
|
||||
LL + #[inline(always|never)]
|
||||
|
|
||||
LL - #[inline(please,no)]
|
||||
LL + #[inline]
|
||||
|
|
||||
|
||||
error[E0534]: expected one argument
|
||||
error[E0539]: malformed `inline` attribute input
|
||||
--> $DIR/invalid-inline.rs:7:1
|
||||
|
|
||||
LL | #[inline()]
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
note: expected a single argument here
|
||||
--> $DIR/invalid-inline.rs:7:9
|
||||
|
|
||||
LL | #[inline()]
|
||||
| ^^
|
||||
help: the following are possible correct uses
|
||||
|
|
||||
LL | #[inline(always|never)]
|
||||
| ++++++++++++
|
||||
LL - #[inline()]
|
||||
LL + #[inline]
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0534`.
|
||||
For more information about this error, try `rustc --explain E0539`.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ fn main() {
|
|||
|
||||
#[inline(XYZ)]
|
||||
let _b = 4;
|
||||
//~^^ ERROR attribute should be applied to function or closure
|
||||
//~^^ ERROR malformed `inline` attribute
|
||||
|
||||
#[repr(nothing)]
|
||||
let _x = 0;
|
||||
|
|
@ -29,7 +29,7 @@ fn main() {
|
|||
|
||||
#[inline(ABC)]
|
||||
foo();
|
||||
//~^^ ERROR attribute should be applied to function or closure
|
||||
//~^^ ERROR malformed `inline` attribute
|
||||
|
||||
let _z = #[repr] 1;
|
||||
//~^ ERROR malformed `repr` attribute
|
||||
|
|
|
|||
|
|
@ -10,6 +10,26 @@ error: malformed `repr` attribute input
|
|||
LL | let _z = #[repr] 1;
|
||||
| ^^^^^^^ help: must be of the form: `#[repr(C)]`
|
||||
|
||||
error[E0539]: malformed `inline` attribute input
|
||||
--> $DIR/issue-43988.rs:10:5
|
||||
|
|
||||
LL | #[inline(XYZ)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: valid arguments are `always` or `never`
|
||||
--> $DIR/issue-43988.rs:10:14
|
||||
|
|
||||
LL | #[inline(XYZ)]
|
||||
| ^^^
|
||||
help: the following are possible correct uses
|
||||
|
|
||||
LL - #[inline(XYZ)]
|
||||
LL + #[inline(always|never)]
|
||||
|
|
||||
LL - #[inline(XYZ)]
|
||||
LL + #[inline]
|
||||
|
|
||||
|
||||
error[E0552]: unrecognized representation hint
|
||||
--> $DIR/issue-43988.rs:14:12
|
||||
|
|
||||
|
|
@ -26,6 +46,26 @@ LL | #[repr(something_not_real)]
|
|||
|
|
||||
= help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
|
||||
|
||||
error[E0539]: malformed `inline` attribute input
|
||||
--> $DIR/issue-43988.rs:30:5
|
||||
|
|
||||
LL | #[inline(ABC)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: valid arguments are `always` or `never`
|
||||
--> $DIR/issue-43988.rs:30:14
|
||||
|
|
||||
LL | #[inline(ABC)]
|
||||
| ^^^
|
||||
help: the following are possible correct uses
|
||||
|
|
||||
LL - #[inline(ABC)]
|
||||
LL + #[inline(always|never)]
|
||||
|
|
||||
LL - #[inline(ABC)]
|
||||
LL + #[inline]
|
||||
|
|
||||
|
||||
error[E0518]: attribute should be applied to function or closure
|
||||
--> $DIR/issue-43988.rs:5:5
|
||||
|
|
||||
|
|
@ -34,23 +74,7 @@ LL | #[inline]
|
|||
LL | let _a = 4;
|
||||
| ----------- not a function or closure
|
||||
|
||||
error[E0518]: attribute should be applied to function or closure
|
||||
--> $DIR/issue-43988.rs:10:5
|
||||
|
|
||||
LL | #[inline(XYZ)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | let _b = 4;
|
||||
| ----------- not a function or closure
|
||||
|
||||
error[E0518]: attribute should be applied to function or closure
|
||||
--> $DIR/issue-43988.rs:30:5
|
||||
|
|
||||
LL | #[inline(ABC)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | foo();
|
||||
| ----- not a function or closure
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0518, E0552.
|
||||
Some errors have detailed explanations: E0518, E0539, E0552.
|
||||
For more information about an error, try `rustc --explain E0518`.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,21 @@
|
|||
error: unused attribute
|
||||
--> $DIR/unused-attr-duplicate.rs:74:1
|
||||
|
|
||||
LL | #[inline(never)]
|
||||
| ^^^^^^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
note: attribute also specified here
|
||||
--> $DIR/unused-attr-duplicate.rs:73:1
|
||||
|
|
||||
LL | #[inline(always)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
note: the lint level is defined here
|
||||
--> $DIR/unused-attr-duplicate.rs:12:9
|
||||
|
|
||||
LL | #![deny(unused_attributes)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr-duplicate.rs:33:1
|
||||
|
|
||||
|
|
@ -9,11 +27,6 @@ note: attribute also specified here
|
|||
|
|
||||
LL | #[no_link]
|
||||
| ^^^^^^^^^^
|
||||
note: the lint level is defined here
|
||||
--> $DIR/unused-attr-duplicate.rs:12:9
|
||||
|
|
||||
LL | #![deny(unused_attributes)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr-duplicate.rs:37:1
|
||||
|
|
@ -102,19 +115,6 @@ note: attribute also specified here
|
|||
LL | #[automatically_derived]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr-duplicate.rs:74:1
|
||||
|
|
||||
LL | #[inline(never)]
|
||||
| ^^^^^^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
note: attribute also specified here
|
||||
--> $DIR/unused-attr-duplicate.rs:73:1
|
||||
|
|
||||
LL | #[inline(always)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr-duplicate.rs:77:1
|
||||
|
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ extern crate std;
|
|||
// issue#97006
|
||||
|
||||
macro_rules! m { ($attr_path: path) => { #[$attr_path] fn f() {} } }
|
||||
#[inline]
|
||||
#[attr="Inline(Hint)")]
|
||||
fn f() { }
|
||||
|
||||
fn main() { }
|
||||
|
|
|
|||
|
|
@ -17,15 +17,6 @@ LL | #[ignore()]
|
|||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
|
||||
|
||||
error: valid forms for the attribute are `#[inline]` and `#[inline(always|never)]`
|
||||
--> $DIR/malformed-regressions.rs:5:1
|
||||
|
|
||||
LL | #[inline = ""]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
|
||||
|
||||
error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]`
|
||||
--> $DIR/malformed-regressions.rs:7:1
|
||||
|
|
||||
|
|
@ -44,5 +35,14 @@ LL | #[link = ""]
|
|||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
|
||||
|
||||
error: valid forms for the attribute are `#[inline(always|never)]` and `#[inline]`
|
||||
--> $DIR/malformed-regressions.rs:5:1
|
||||
|
|
||||
LL | #[inline = ""]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#[inline(unknown)] //~ ERROR E0535
|
||||
#[inline(unknown)] //~ ERROR malformed `inline` attribute
|
||||
pub fn something() {}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,23 @@
|
|||
error[E0535]: invalid argument
|
||||
error[E0539]: malformed `inline` attribute input
|
||||
--> $DIR/E0535.rs:1:1
|
||||
|
|
||||
LL | #[inline(unknown)]
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: valid arguments are `always` or `never`
|
||||
--> $DIR/E0535.rs:1:10
|
||||
|
|
||||
LL | #[inline(unknown)]
|
||||
| ^^^^^^^
|
||||
help: the following are possible correct uses
|
||||
|
|
||||
LL - #[inline(unknown)]
|
||||
LL + #[inline(always|never)]
|
||||
|
|
||||
LL - #[inline(unknown)]
|
||||
LL + #[inline]
|
||||
|
|
||||
= help: valid inline arguments are `always` and `never`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0535`.
|
||||
For more information about this error, try `rustc --explain E0539`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue