diff options
Diffstat (limited to 'compiler/rustc_attr_parsing/src/attributes')
8 files changed, 113 insertions, 63 deletions
| diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs index 81192f902a2..21b01a8d071 100644 --- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs +++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs @@ -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>, diff --git a/compiler/rustc_attr_parsing/src/attributes/confusables.rs b/compiler/rustc_attr_parsing/src/attributes/confusables.rs index afd3c012f05..0be9d690c32 100644 --- a/compiler/rustc_attr_parsing/src/attributes/confusables.rs +++ b/compiler/rustc_attr_parsing/src/attributes/confusables.rs @@ -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); - } - - this.first_span.get_or_insert(cx.attr_span); - })]; + 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; + }; + + 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() { diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs index 1faee41c2a9..692f587ba03 100644 --- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs +++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs @@ -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(); diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs index fecddde930a..da56656e3ed 100644 --- a/compiler/rustc_attr_parsing/src/attributes/inline.rs +++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs @@ -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)) } diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 0b9e9adcfbc..fa2a6087506 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -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)) } diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 753b2366b41..6fb618541e3 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -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>, diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 6589a51db2b..fba725ae164 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -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; }), diff --git a/compiler/rustc_attr_parsing/src/attributes/transparency.rs b/compiler/rustc_attr_parsing/src/attributes/transparency.rs index 16ad9d03e50..b0f5dac7fe2 100644 --- a/compiler/rustc_attr_parsing/src/attributes/transparency.rs +++ b/compiler/rustc_attr_parsing/src/attributes/transparency.rs @@ -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()) { | 
