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
2 changes: 0 additions & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4010,9 +4010,7 @@ dependencies = [
name = "rustc_feature"
version = "0.0.0"
dependencies = [
"rustc_ast",
"rustc_data_structures",
"rustc_hir",
"rustc_span",
"serde",
"serde_json",
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/autodiff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::str::FromStr;

use rustc_ast::LitKind;
use rustc_ast::expand::autodiff_attrs::{DiffActivity, DiffMode};
use rustc_feature::{AttributeStability, AttributeTemplate, template};
use rustc_feature::AttributeStability;
use rustc_hir::attrs::{AttributeKind, RustcAutodiff};
use rustc_hir::{MethodKind, Target};
use rustc_span::{Symbol, sym};
Expand All @@ -13,7 +13,7 @@ use crate::attributes::prelude::Allow;
use crate::context::AcceptContext;
use crate::parser::{ArgParser, MetaItemOrLitParser};
use crate::target_checking::AllowedTargets;
use crate::unstable;
use crate::{AttributeTemplate, template, unstable};

pub(crate) struct RustcAutodiffParser;

Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_attr_parsing/src/attributes/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ use rustc_ast::token::Delimiter;
use rustc_ast::tokenstream::DelimSpan;
use rustc_ast::{AttrItem, Attribute, LitKind, ast, token};
use rustc_errors::{Applicability, Diagnostic, PResult, msg};
use rustc_feature::{
AttrSuggestionStyle, AttributeTemplate, Features, GatedCfg, find_gated_cfg, template,
};
use rustc_feature::{Features, GatedCfg, find_gated_cfg};
use rustc_hir::attrs::CfgEntry;
use rustc_hir::{AttrPath, RustcVersion, Target};
use rustc_parse::parser::{ForceCollect, Parser, Recovery};
Expand All @@ -28,7 +26,10 @@ use crate::session_diagnostics::{
AttributeParseError, AttributeParseErrorReason, CfgAttrBadDelim, MetaBadDelimSugg,
ParsedDescription,
};
use crate::{AttributeParser, check_cfg, parse_version, session_diagnostics};
use crate::{
AttrSuggestionStyle, AttributeParser, AttributeTemplate, check_cfg, parse_version,
session_diagnostics, template,
};

pub const CFG_TEMPLATE: AttributeTemplate = template!(
List: &["predicate"],
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/cfg_select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{AttrStyle, NodeId, token};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{Diagnostic, MultiSpan};
use rustc_feature::{AttributeTemplate, Features};
use rustc_feature::Features;
use rustc_hir::attrs::CfgEntry;
use rustc_hir::{AttrPath, Target};
use rustc_parse::exp;
Expand All @@ -14,7 +14,9 @@ use rustc_span::{ErrorGuaranteed, Span, Symbol, sym};

use crate::attributes::AttributeSafety;
use crate::parser::{AllowExprMetavar, MetaItemOrLitParser};
use crate::{AttributeParser, ParsedDescription, ShouldEmit, diagnostics, parse_cfg_entry};
use crate::{
AttributeParser, AttributeTemplate, ParsedDescription, ShouldEmit, diagnostics, parse_cfg_entry,
};

#[derive(Clone)]
pub enum CfgSelectPredicate {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rustc_feature::{AttributeStability, AttributeTemplate, template};
use rustc_feature::AttributeStability;
use rustc_hir::Target;
use rustc_hir::attrs::AttributeKind;
use rustc_session::lint::builtin::{
Expand All @@ -11,6 +11,7 @@ use crate::context::AcceptContext;
use crate::diagnostics::IncorrectDoNotRecommendLocation;
use crate::parser::ArgParser;
use crate::target_checking::{ALL_TARGETS, AllowedTargets};
use crate::{AttributeTemplate, template};

pub(crate) struct DoNotRecommendParser;
impl SingleAttributeParser for DoNotRecommendParser {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rustc_feature::{AttributeStability, template};
use rustc_feature::AttributeStability;
use rustc_hir::attrs::AttributeKind;
use rustc_session::lint::builtin::MISPLACED_DIAGNOSTIC_ATTRIBUTES;
use rustc_span::sym;
Expand All @@ -9,6 +9,7 @@ use crate::context::AcceptContext;
use crate::diagnostics::DiagnosticOnMoveOnlyForAdt;
use crate::parser::ArgParser;
use crate::target_checking::{ALL_TARGETS, AllowedTargets};
use crate::template;

#[derive(Default)]
pub(crate) struct OnMoveParser {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/doc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rustc_ast::ast::{AttrStyle, LitKind, MetaItemLit};
use rustc_errors::{Applicability, msg};
use rustc_feature::{AttributeStability, template};
use rustc_feature::AttributeStability;
use rustc_hir::Target;
use rustc_hir::attrs::{
AttributeKind, CfgEntry, CfgHideShow, CfgInfo, DocAttribute, DocInline, HideOrShow,
Expand All @@ -10,7 +10,7 @@ use rustc_span::{Span, Symbol, edition, sym};
use thin_vec::ThinVec;

use super::prelude::{ALL_TARGETS, AllowedTargets};
use super::{AcceptMapping, AttributeParser};
use super::{AcceptMapping, AttributeParser, template};
use crate::context::{AcceptContext, FinalizeContext};
use crate::diagnostics::{
AttrCrateLevelOnly, DocAliasDuplicated, DocAutoCfgExpectsHideOrShow,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/dummy.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use rustc_feature::{AttributeStability, AttributeTemplate, template};
use rustc_feature::AttributeStability;
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Symbol, sym};

use crate::attributes::{OnDuplicate, SingleAttributeParser};
use crate::context::AcceptContext;
use crate::parser::ArgParser;
use crate::target_checking::AllowedTargets;
use crate::unstable;
use crate::{AttributeTemplate, template, unstable};

pub(crate) struct RustcDummyParser;
impl SingleAttributeParser for RustcDummyParser {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

use std::marker::PhantomData;

use rustc_feature::{AttributeStability, AttributeTemplate, template};
use rustc_feature::AttributeStability;
use rustc_hir::attrs::AttributeKind;
use rustc_span::edition::Edition;
use rustc_span::{Span, Symbol};
Expand All @@ -30,6 +30,7 @@ use crate::context::{AcceptContext, FinalizeContext};
use crate::parser::ArgParser;
use crate::session_diagnostics::UnusedMultiple;
use crate::target_checking::AllowedTargets;
use crate::{AttributeTemplate, template};

/// All the parsers require roughly the same imports, so this prelude has most of the often-needed ones.
mod prelude;
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_attr_parsing/src/attributes/prelude.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
// data structures
#[doc(hidden)]
pub(super) use rustc_feature::{AttributeTemplate, template};
#[doc(hidden)]
pub(super) use rustc_hir::attrs::AttributeKind;
#[doc(hidden)]
pub(super) use rustc_hir::{MethodKind, Target};
Expand All @@ -27,3 +25,4 @@ pub(super) use crate::target_checking::Policy::{Allow, Error, Warn};
pub(super) use crate::target_checking::{ALL_TARGETS, AllowedTargets};
#[doc(hidden)]
pub(super) use crate::unstable;
pub(super) use crate::{AttributeTemplate, template};
4 changes: 2 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/prototype.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Attributes that are only used on function prototypes.

use rustc_feature::{AttributeStability, AttributeTemplate, template};
use rustc_feature::AttributeStability;
use rustc_hir::Target;
use rustc_hir::attrs::{AttributeKind, MirDialect, MirPhase};
use rustc_span::{Span, Symbol, sym};
Expand All @@ -10,7 +10,7 @@ use crate::context::AcceptContext;
use crate::parser::{ArgParser, NameValueParser};
use crate::target_checking::AllowedTargets;
use crate::target_checking::Policy::Allow;
use crate::{session_diagnostics, unstable};
use crate::{AttributeTemplate, session_diagnostics, template, unstable};

pub(crate) struct CustomMirParser;

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
use rustc_ast::{AttrStyle, MetaItemLit, Safety};
use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan};
use rustc_feature::{AttrSuggestionStyle, AttributeStability, AttributeTemplate};
use rustc_feature::AttributeStability;
use rustc_hir::AttrPath;
use rustc_hir::attrs::AttributeKind;
use rustc_parse::parser::Recovery;
Expand Down Expand Up @@ -71,7 +71,7 @@ use crate::session_diagnostics::{
ParsedDescription,
};
use crate::target_checking::AllowedTargets;
use crate::{AttributeParser, EmitAttribute};
use crate::{AttrSuggestionStyle, AttributeParser, AttributeTemplate, EmitAttribute};

type GroupType = LazyLock<GroupTypeInner>;

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_attr_parsing/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc_ast::token::DocFragmentKind;
use rustc_ast::{AttrItemKind, AttrStyle, CRATE_NODE_ID, NodeId, Safety};
use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan};
use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, Features};
use rustc_feature::{BUILTIN_ATTRIBUTE_MAP, Features};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, Target};
use rustc_lint_defs::RegisteredTools;
Expand All @@ -23,7 +23,7 @@ use crate::context::{
use crate::early_parsed::{EARLY_PARSED_ATTRIBUTES, EarlyParsedState};
use crate::parser::{AllowExprMetavar, ArgParser, PathParser, RefPathParser};
use crate::session_diagnostics::ParsedDescription;
use crate::{OmitDoc, ShouldEmit};
use crate::{AttributeTemplate, OmitDoc, ShouldEmit};

pub struct EmitAttribute(
pub Box<
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_attr_parsing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ mod safety;
mod session_diagnostics;
mod stability;
mod target_checking;
mod template;
pub mod validate_attr;

pub use attributes::AttributeSafety;
Expand All @@ -117,3 +118,4 @@ pub use context::{OmitDoc, ShouldEmit};
pub use interface::{AttributeParser, EmitAttribute};
pub use rustc_parse::parser::Recovery;
pub use session_diagnostics::ParsedDescription;
pub use template::{AttrSuggestionStyle, AttributeTemplate};
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ use rustc_errors::codes::*;
use rustc_errors::{
Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
};
use rustc_feature::AttributeTemplate;
use rustc_hir::AttrPath;
use rustc_hir::attrs::{MirDialect, MirPhase};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{Span, Symbol};
use rustc_target::spec::TargetTuple;

use crate::AttributeTemplate;
use crate::context::Suggestion;

#[derive(Diagnostic)]
Expand Down
118 changes: 118 additions & 0 deletions compiler/rustc_attr_parsing/src/template.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
use rustc_ast::ast::Safety;
use rustc_hir::AttrStyle;
use rustc_span::Symbol;

/// A template that the attribute input must match.
/// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now.
#[derive(Clone, Copy, Default)]
pub struct AttributeTemplate {
/// If `true`, the attribute is allowed to be a bare word like `#[test]`.
pub word: bool,
/// If `Some`, the attribute is allowed to take a list of items like `#[allow(..)]`.
pub list: Option<&'static [&'static str]>,
/// If non-empty, the attribute is allowed to take a list containing exactly
/// one of the listed words, like `#[coverage(off)]`.
pub one_of: &'static [Symbol],
/// If `Some`, the attribute is allowed to be a name/value pair where the
/// value is a string, like `#[must_use = "reason"]`.
pub name_value_str: Option<&'static [&'static str]>,
/// A link to the document for this attribute.
pub docs: Option<&'static str>,
}

pub enum AttrSuggestionStyle {
/// The suggestion is styled for a normal attribute.
/// The `AttrStyle` determines whether this is an inner or outer attribute.
Attribute(AttrStyle),
/// The suggestion is styled for an attribute embedded into another attribute.
/// For example, attributes inside `#[cfg_attr(true, attr(...)]`.
EmbeddedAttribute,
/// The suggestion is styled for macros that are parsed with attribute parsers.
/// For example, the `cfg!(predicate)` macro.
Macro,
}

impl AttributeTemplate {
pub fn suggestions(
&self,
style: AttrSuggestionStyle,
safety: Safety,
name: impl std::fmt::Display,
) -> Vec<String> {
let (start, macro_call, end) = match style {
AttrSuggestionStyle::Attribute(AttrStyle::Outer) => ("#[", "", "]"),
AttrSuggestionStyle::Attribute(AttrStyle::Inner) => ("#![", "", "]"),
AttrSuggestionStyle::Macro => ("", "!", ""),
AttrSuggestionStyle::EmbeddedAttribute => ("", "", ""),
};

let mut suggestions = vec![];

let (safety_start, safety_end) = match safety {
Safety::Unsafe(_) => ("unsafe(", ")"),
_ => ("", ""),
};

if self.word {
debug_assert!(macro_call.is_empty(), "Macro suggestions use list style");
suggestions.push(format!("{start}{safety_start}{name}{safety_end}{end}"));
}
if let Some(descr) = self.list {
for descr in descr {
suggestions.push(format!(
"{start}{safety_start}{name}{macro_call}({descr}){safety_end}{end}"
));
}
}
suggestions.extend(
self.one_of
.iter()
.map(|&word| format!("{start}{safety_start}{name}({word}){safety_end}{end}")),
);
if let Some(descr) = self.name_value_str {
debug_assert!(macro_call.is_empty(), "Macro suggestions use list style");
for descr in descr {
suggestions
.push(format!("{start}{safety_start}{name} = \"{descr}\"{safety_end}{end}"));
}
}
suggestions.sort();

suggestions
}
}

/// 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) => { $crate::template!(@ true, None, &[], None, None) };
(Word, $link: literal) => { $crate::template!(@ true, None, &[], None, Some($link)) };
(List: $descr: expr) => { $crate::template!(@ false, Some($descr), &[], None, None) };
(List: $descr: expr, $link: literal) => { $crate::template!(@ false, Some($descr), &[], None, Some($link)) };
(OneOf: $one_of: expr) => { $crate::template!(@ false, None, $one_of, None, None) };
(NameValueStr: [$($descr: literal),* $(,)?]) => { $crate::template!(@ false, None, &[], Some(&[$($descr,)*]), None) };
(NameValueStr: [$($descr: literal),* $(,)?], $link: literal) => { $crate::template!(@ false, None, &[], Some(&[$($descr,)*]), Some($link)) };
(NameValueStr: $descr: literal) => { $crate::template!(@ false, None, &[], Some(&[$descr]), None) };
(NameValueStr: $descr: literal, $link: literal) => { $crate::template!(@ false, None, &[], Some(&[$descr]), Some($link)) };
(Word, List: $descr: expr) => { $crate::template!(@ true, Some($descr), &[], None, None) };
(Word, List: $descr: expr, $link: literal) => { $crate::template!(@ true, Some($descr), &[], None, Some($link)) };
(Word, NameValueStr: $descr: expr) => { $crate::template!(@ true, None, &[], Some(&[$descr]), None) };
(Word, NameValueStr: $descr: expr, $link: literal) => { $crate::template!(@ true, None, &[], Some(&[$descr]), Some($link)) };
(List: $descr1: expr, NameValueStr: $descr2: expr) => {
$crate::template!(@ false, Some($descr1), &[], Some(&[$descr2]), None)
};
(List: $descr1: expr, NameValueStr: $descr2: expr, $link: literal) => {
$crate::template!(@ false, Some($descr1), &[], Some(&[$descr2]), Some($link))
};
(Word, List: $descr1: expr, NameValueStr: $descr2: expr) => {
$crate::template!(@ true, Some($descr1), &[], Some(&[$descr2]), None)
};
(Word, List: $descr1: expr, NameValueStr: $descr2: expr, $link: literal) => {
$crate::template!(@ true, Some($descr1), &[], Some(&[$descr2]), Some($link))
};
(@ $word: expr, $list: expr, $one_of: expr, $name_value_str: expr, $link: expr) => { $crate::AttributeTemplate {
word: $word, list: $list, one_of: $one_of, name_value_str: $name_value_str, docs: $link,
} };
}
4 changes: 2 additions & 2 deletions compiler/rustc_attr_parsing/src/validate_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ use rustc_ast::{
self as ast, AttrArgs, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind, Safety,
};
use rustc_errors::{Applicability, Diagnostic, PResult};
use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, template};
use rustc_feature::BUILTIN_ATTRIBUTE_MAP;
use rustc_hir::AttrPath;
use rustc_parse::parse_in;
use rustc_session::errors::report_lit_error;
use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
use rustc_session::parse::ParseSess;
use rustc_span::{Span, Symbol, sym};

use crate::{AttributeParser, session_diagnostics as errors};
use crate::{AttributeParser, AttributeTemplate, session_diagnostics as errors, template};

pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
if attr.is_doc_comment() || attr.has_name(sym::cfg_trace) || attr.has_name(sym::cfg_attr_trace)
Expand Down
Loading
Loading