Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 7 additions & 33 deletions compiler/rustc_attr_parsing/src/attributes/crate_level.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,7 @@ impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
const TYPE: AttributeType = AttributeType::CrateLevel;

// because it's a crate-level attribute, we already warn about it.
// Putting target limitations here would give duplicate warnings
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let ArgParser::NameValue(n) = args else {
Expand Down Expand Up @@ -76,11 +72,7 @@ impl<S: Stage> SingleAttributeParser<S> for RecursionLimitParser {
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute");
const TYPE: AttributeType = AttributeType::CrateLevel;

// because it's a crate-level attribute, we already warn about it.
// Putting target limitations here would give duplicate warnings
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
Expand All @@ -103,11 +95,7 @@ impl<S: Stage> SingleAttributeParser<S> for MoveSizeLimitParser {
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
const TYPE: AttributeType = AttributeType::CrateLevel;

// because it's a crate-level attribute, we already warn about it.
// Putting target limitations here would give duplicate warnings
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
Expand All @@ -130,11 +118,7 @@ impl<S: Stage> SingleAttributeParser<S> for TypeLengthLimitParser {
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
const TYPE: AttributeType = AttributeType::CrateLevel;

// because it's a crate-level attribute, we already warn about it.
// Putting target limitations here would give duplicate warnings
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
Expand All @@ -157,11 +141,7 @@ impl<S: Stage> SingleAttributeParser<S> for PatternComplexityLimitParser {
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
const TYPE: AttributeType = AttributeType::CrateLevel;

// because it's a crate-level attribute, we already warn about it.
// Putting target limitations here would give duplicate warnings
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
Expand All @@ -182,21 +162,15 @@ pub(crate) struct NoCoreParser;
impl<S: Stage> NoArgsAttributeParser<S> for NoCoreParser {
const PATH: &[Symbol] = &[sym::no_core];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
// because it's a crate-level attribute, we already warn about it.
// Putting target limitations here would give duplicate warnings
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoCore;
const TYPE: AttributeType = AttributeType::CrateLevel;
}

pub(crate) struct NoStdParser;

impl<S: Stage> NoArgsAttributeParser<S> for NoStdParser {
const PATH: &[Symbol] = &[sym::no_std];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
// because it's a crate-level attribute, we already warn about it.
// Putting target limitations here would give duplicate warnings
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoStd;
const TYPE: AttributeType = AttributeType::CrateLevel;
}
18 changes: 1 addition & 17 deletions compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,11 @@
//! - [`CombineAttributeParser`](crate::attributes::CombineAttributeParser): makes it easy to implement an attribute which should combine the
//! contents of attributes, if an attribute appear multiple times in a list
//!
//! By default, attributes are allowed anywhere. When adding an attribute that should only be used
//! at the crate root, consider setting the `TYPE` in the parser trait to
//! [`AttributeType::CrateLevel`](rustc_feature::AttributeType::CrateLevel).
//!
//! Attributes should be added to `crate::context::ATTRIBUTE_PARSERS` to be parsed.

use std::marker::PhantomData;

use rustc_feature::{AttributeTemplate, AttributeType, template};
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Span, Symbol};
use thin_vec::ThinVec;
Expand Down Expand Up @@ -89,11 +85,8 @@ pub(crate) trait AttributeParser<S: Stage>: Default + 'static {
///
/// If an attribute has this symbol, the `accept` function will be called on it.
const ATTRIBUTES: AcceptMapping<Self, S>;

const ALLOWED_TARGETS: AllowedTargets;

const TYPE: AttributeType = AttributeType::Normal;

/// The parser has gotten a chance to accept the attributes on an item,
/// here it can produce an attribute.
///
Expand Down Expand Up @@ -135,8 +128,6 @@ pub(crate) trait SingleAttributeParser<S: Stage>: 'static {
/// The template this attribute parser should implement. Used for diagnostics.
const TEMPLATE: AttributeTemplate;

const TYPE: AttributeType = AttributeType::Normal;

/// Converts a single syntactical attribute to a single semantic attribute, or [`AttributeKind`]
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind>;
}
Expand Down Expand Up @@ -183,8 +174,6 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
)];
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;

const TYPE: AttributeType = T::TYPE;

fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
Some(self.1?.0)
}
Expand Down Expand Up @@ -269,7 +258,6 @@ pub(crate) trait NoArgsAttributeParser<S: Stage>: 'static {
const PATH: &[Symbol];
const ON_DUPLICATE: OnDuplicate<S>;
const ALLOWED_TARGETS: AllowedTargets;
const TYPE: AttributeType = AttributeType::Normal;

/// Create the [`AttributeKind`] given attribute's [`Span`].
const CREATE: fn(Span) -> AttributeKind;
Expand All @@ -289,7 +277,6 @@ impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for Without
const ON_DUPLICATE: OnDuplicate<S> = T::ON_DUPLICATE;
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
const TEMPLATE: AttributeTemplate = template!(Word);
const TYPE: AttributeType = T::TYPE;

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
if let Err(span) = args.no_args() {
Expand Down Expand Up @@ -323,8 +310,6 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
/// The template this attribute parser should implement. Used for diagnostics.
const TEMPLATE: AttributeTemplate;

const TYPE: AttributeType = AttributeType::Normal;

/// Converts a single syntactical attribute to a number of elements of the semantic attribute, or [`AttributeKind`]
fn extend<'c>(
cx: &'c mut AcceptContext<'_, '_, S>,
Expand Down Expand Up @@ -360,7 +345,6 @@ impl<T: CombineAttributeParser<S>, S: Stage> AttributeParser<S> for Combine<T, S
group.items.extend(T::extend(cx, args))
})];
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
const TYPE: AttributeType = T::TYPE;

fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
if let Some(first_span) = self.first_span {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/prelude.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// data structures
#[doc(hidden)]
pub(super) use rustc_feature::{AttributeTemplate, AttributeType, template};
pub(super) use rustc_feature::{AttributeTemplate, template};
#[doc(hidden)]
pub(super) use rustc_hir::attrs::AttributeKind;
#[doc(hidden)]
Expand Down
5 changes: 1 addition & 4 deletions compiler/rustc_attr_parsing/src/attributes/traits.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::mem;

use rustc_feature::AttributeType;

use super::prelude::*;
use crate::attributes::{
AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
Expand Down Expand Up @@ -155,8 +153,7 @@ pub(crate) struct CoherenceIsCoreParser;
impl<S: Stage> NoArgsAttributeParser<S> for CoherenceIsCoreParser {
const PATH: &[Symbol] = &[sym::rustc_coherence_is_core];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const TYPE: AttributeType = AttributeType::CrateLevel;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CoherenceIsCore;
}

Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::sync::LazyLock;
use private::Sealed;
use rustc_ast::{AttrStyle, CRATE_NODE_ID, MetaItemLit, NodeId};
use rustc_errors::{Diag, Diagnostic, Level};
use rustc_feature::{AttributeTemplate, AttributeType};
use rustc_feature::AttributeTemplate;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
use rustc_hir::{AttrPath, CRATE_HIR_ID, HirId};
Expand Down Expand Up @@ -83,7 +83,6 @@ pub(super) struct GroupTypeInnerAccept<S: Stage> {
pub(super) template: AttributeTemplate,
pub(super) accept_fn: AcceptFn<S>,
pub(super) allowed_targets: AllowedTargets,
pub(super) attribute_type: AttributeType,
}

type AcceptFn<S> =
Expand Down Expand Up @@ -133,7 +132,6 @@ macro_rules! attribute_parsers {
})
}),
allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
attribute_type: <$names as crate::attributes::AttributeParser<$stage>>::TYPE,
});
}

Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_attr_parsing/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,6 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {

(accept.accept_fn)(&mut cx, args);
if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) {
Self::check_type(accept.attribute_type, target, &mut cx);
Self::check_target(&accept.allowed_targets, target, &mut cx);
}
}
Expand Down
15 changes: 12 additions & 3 deletions compiler/rustc_attr_parsing/src/target_checking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::borrow::Cow;

use rustc_ast::AttrStyle;
use rustc_errors::DiagArgValue;
use rustc_feature::{AttributeType, Features};
use rustc_feature::Features;
use rustc_hir::lints::AttributeLintKind;
use rustc_hir::{MethodKind, Target};

Expand All @@ -14,6 +14,11 @@ use crate::session_diagnostics::InvalidTarget;
pub(crate) enum AllowedTargets {
AllowList(&'static [Policy]),
AllowListWarnRest(&'static [Policy]),
/// Special, and not the same as `AllowList(&[Allow(Target::Crate)])`.
/// For crate-level attributes we emit a specific set of lints to warn
/// people about accidentally not using them on the crate.
/// Only use this for attributes that are *exclusively* valid at the crate level.
CrateLevel,
}

pub(crate) enum AllowedResult {
Expand Down Expand Up @@ -43,13 +48,15 @@ impl AllowedTargets {
AllowedResult::Warn
}
}
AllowedTargets::CrateLevel => AllowedResult::Allowed,
}
}

pub(crate) fn allowed_targets(&self) -> Vec<Target> {
match self {
AllowedTargets::AllowList(list) => list,
AllowedTargets::AllowListWarnRest(list) => list,
AllowedTargets::CrateLevel => ALL_TARGETS,
}
.iter()
.filter_map(|target| match target {
Expand All @@ -74,6 +81,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
target: Target,
cx: &mut AcceptContext<'_, 'sess, S>,
) {
Self::check_type(matches!(allowed_targets, AllowedTargets::CrateLevel), target, cx);

match allowed_targets.is_allowed(target) {
AllowedResult::Allowed => {}
AllowedResult::Warn => {
Expand Down Expand Up @@ -109,7 +118,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
}

pub(crate) fn check_type(
attribute_type: AttributeType,
crate_level: bool,
target: Target,
cx: &mut AcceptContext<'_, 'sess, S>,
) {
Expand All @@ -119,7 +128,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
return;
}

if attribute_type != AttributeType::CrateLevel {
if !crate_level {
return;
}

Expand Down
Loading