diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 61ebc73182c0..485af5ab1d01 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -7,7 +7,6 @@ use std::sync::Arc; use std::{fmt, mem, ops}; use itertools::Either; -use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::thin_vec::{ThinVec, thin_vec}; use rustc_hir as hir; @@ -29,12 +28,6 @@ mod tests; #[cfg_attr(test, derive(PartialEq))] pub(crate) struct Cfg(CfgEntry); -#[derive(PartialEq, Debug)] -pub(crate) struct InvalidCfgError { - pub(crate) msg: &'static str, - pub(crate) span: Span, -} - /// Whether the configuration consists of just `Cfg` or `Not`. fn is_simple_cfg(cfg: &CfgEntry) -> bool { match cfg { @@ -105,106 +98,6 @@ fn should_capitalize_first_letter(cfg: &CfgEntry) -> bool { } impl Cfg { - /// Parses a `MetaItemInner` into a `Cfg`. - fn parse_nested( - nested_cfg: &MetaItemInner, - exclude: &FxHashSet, - ) -> Result, InvalidCfgError> { - match nested_cfg { - MetaItemInner::MetaItem(cfg) => Cfg::parse_without(cfg, exclude), - MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => { - Ok(Some(Cfg(CfgEntry::Bool(*b, DUMMY_SP)))) - } - MetaItemInner::Lit(lit) => { - Err(InvalidCfgError { msg: "unexpected literal", span: lit.span }) - } - } - } - - fn parse_without( - cfg: &MetaItem, - exclude: &FxHashSet, - ) -> Result, InvalidCfgError> { - let name = match cfg.ident() { - Some(ident) => ident.name, - None => { - return Err(InvalidCfgError { - msg: "expected a single identifier", - span: cfg.span, - }); - } - }; - match cfg.kind { - MetaItemKind::Word => { - if exclude.contains(&NameValueCfg::new(name)) { - Ok(None) - } else { - Ok(Some(Cfg(CfgEntry::NameValue { name, value: None, span: DUMMY_SP }))) - } - } - MetaItemKind::NameValue(ref lit) => match lit.kind { - LitKind::Str(value, _) => { - if exclude.contains(&NameValueCfg::new_value(name, value)) { - Ok(None) - } else { - Ok(Some(Cfg(CfgEntry::NameValue { - name, - value: Some(value), - span: DUMMY_SP, - }))) - } - } - _ => Err(InvalidCfgError { - // FIXME: if the main #[cfg] syntax decided to support non-string literals, - // this should be changed as well. - msg: "value of cfg option should be a string literal", - span: lit.span, - }), - }, - MetaItemKind::List(ref items) => { - let orig_len = items.len(); - let mut sub_cfgs = - items.iter().filter_map(|i| Cfg::parse_nested(i, exclude).transpose()); - let ret = match name { - sym::all => { - sub_cfgs.try_fold(Cfg(CfgEntry::Bool(true, DUMMY_SP)), |x, y| Ok(x & y?)) - } - sym::any => { - sub_cfgs.try_fold(Cfg(CfgEntry::Bool(false, DUMMY_SP)), |x, y| Ok(x | y?)) - } - sym::not => { - if orig_len == 1 { - let mut sub_cfgs = sub_cfgs.collect::>(); - if sub_cfgs.len() == 1 { - Ok(!sub_cfgs.pop().unwrap()?) - } else { - return Ok(None); - } - } else { - Err(InvalidCfgError { msg: "expected 1 cfg-pattern", span: cfg.span }) - } - } - _ => Err(InvalidCfgError { msg: "invalid predicate", span: cfg.span }), - }; - match ret { - Ok(c) => Ok(Some(c)), - Err(e) => Err(e), - } - } - } - } - - /// Parses a `MetaItem` into a `Cfg`. - /// - /// The `MetaItem` should be the content of the `#[cfg(...)]`, e.g., `unix` or - /// `target_os = "redox"`. - /// - /// If the content is not properly formatted, it will return an error indicating what and where - /// the error is. - pub(crate) fn parse(cfg: &MetaItemInner) -> Result { - Self::parse_nested(cfg, &FxHashSet::default()).map(|ret| ret.unwrap()) - } - /// Renders the configuration for human display, as a short HTML description. pub(crate) fn render_short_html(&self) -> String { let mut msg = Display(&self.0, Format::ShortHtml).to_string(); @@ -644,10 +537,6 @@ impl NameValueCfg { fn new(name: Symbol) -> Self { Self { name, value: None } } - - fn new_value(name: Symbol, value: Symbol) -> Self { - Self { name, value: Some(value) } - } } impl<'a> From<&'a CfgEntry> for NameValueCfg { @@ -751,15 +640,6 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator tcx: TyCtxt<'_>, cfg_info: &mut CfgInfo, ) -> Option> { - fn single(it: T) -> Option { - let mut iter = it.into_iter(); - let item = iter.next()?; - if iter.next().is_some() { - return None; - } - Some(item) - } - fn check_changed_auto_active_status( changed_auto_active_status: &mut Option, attr_span: Span, @@ -859,12 +739,11 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator } continue; } else if !cfg_info.parent_is_doc_cfg - && let Some(name) = attr.name() - && matches!(name, sym::cfg | sym::cfg_trace) - && let Some(attr) = single(attr.meta_item_list()?) - && let Ok(new_cfg) = Cfg::parse(&attr) + && let hir::Attribute::Parsed(AttributeKind::CfgTrace(cfgs)) = attr { - cfg_info.current_cfg &= new_cfg; + for (new_cfg, _) in cfgs { + cfg_info.current_cfg &= Cfg(new_cfg.clone()); + } } } diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs index 09316ead76ac..e0c21865d8df 100644 --- a/src/librustdoc/clean/cfg/tests.rs +++ b/src/librustdoc/clean/cfg/tests.rs @@ -1,8 +1,5 @@ -use rustc_ast::ast::LitIntType; -use rustc_ast::{MetaItemInner, MetaItemLit, Path, Safety, StrStyle}; use rustc_data_structures::thin_vec::thin_vec; use rustc_hir::attrs::CfgEntry; -use rustc_span::symbol::{Ident, kw}; use rustc_span::{DUMMY_SP, create_default_session_globals_then}; use super::*; @@ -28,10 +25,6 @@ fn name_value_cfg_e(name: &str, value: &str) -> CfgEntry { } } -fn dummy_lit(symbol: Symbol, kind: LitKind) -> MetaItemInner { - MetaItemInner::Lit(MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP }) -} - fn cfg_all(v: ThinVec) -> Cfg { Cfg(cfg_all_e(v)) } @@ -52,51 +45,6 @@ fn cfg_not(v: CfgEntry) -> Cfg { Cfg(CfgEntry::Not(Box::new(v), DUMMY_SP)) } -fn dummy_meta_item_word(name: &str) -> MetaItemInner { - MetaItemInner::MetaItem(MetaItem { - unsafety: Safety::Default, - path: Path::from_ident(Ident::from_str(name)), - kind: MetaItemKind::Word, - span: DUMMY_SP, - }) -} - -fn dummy_meta_item_name_value(name: &str, symbol: Symbol, kind: LitKind) -> MetaItemInner { - let lit = MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP }; - MetaItemInner::MetaItem(MetaItem { - unsafety: Safety::Default, - path: Path::from_ident(Ident::from_str(name)), - kind: MetaItemKind::NameValue(lit), - span: DUMMY_SP, - }) -} - -macro_rules! dummy_meta_item_list { - ($name:ident, [$($list:ident),* $(,)?]) => { - MetaItemInner::MetaItem(MetaItem { - unsafety: Safety::Default, - path: Path::from_ident(Ident::from_str(stringify!($name))), - kind: MetaItemKind::List(thin_vec![ - $( - dummy_meta_item_word(stringify!($list)), - )* - ]), - span: DUMMY_SP, - }) - }; - - ($name:ident, [$($list:expr),* $(,)?]) => { - MetaItemInner::MetaItem(MetaItem { - unsafety: Safety::Default, - path: Path::from_ident(Ident::from_str(stringify!($name))), - kind: MetaItemKind::List(thin_vec![ - $($list,)* - ]), - span: DUMMY_SP, - }) - }; -} - fn cfg_true() -> Cfg { Cfg(CfgEntry::Bool(true, DUMMY_SP)) } @@ -303,87 +251,6 @@ fn test_cfg_or() { }) } -#[test] -fn test_parse_ok() { - create_default_session_globals_then(|| { - let r#true = Symbol::intern("true"); - let mi = dummy_lit(r#true, LitKind::Bool(true)); - assert_eq!(Cfg::parse(&mi), Ok(cfg_true())); - - let r#false = Symbol::intern("false"); - let mi = dummy_lit(r#false, LitKind::Bool(false)); - assert_eq!(Cfg::parse(&mi), Ok(cfg_false())); - - let mi = dummy_meta_item_word("all"); - assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all"))); - - let done = Symbol::intern("done"); - let mi = dummy_meta_item_name_value("all", done, LitKind::Str(done, StrStyle::Cooked)); - assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done"))); - - let mi = dummy_meta_item_list!(all, [a, b]); - assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") & word_cfg("b"))); - - let mi = dummy_meta_item_list!(any, [a, b]); - assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") | word_cfg("b"))); - - let mi = dummy_meta_item_list!(not, [a]); - assert_eq!(Cfg::parse(&mi), Ok(!word_cfg("a"))); - - let mi = dummy_meta_item_list!( - not, - [dummy_meta_item_list!( - any, - [dummy_meta_item_word("a"), dummy_meta_item_list!(all, [b, c]),] - ),] - ); - assert_eq!(Cfg::parse(&mi), Ok(!(word_cfg("a") | (word_cfg("b") & word_cfg("c"))))); - - let mi = dummy_meta_item_list!(all, [a, b, c]); - assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") & word_cfg("b") & word_cfg("c"))); - }) -} - -#[test] -fn test_parse_err() { - create_default_session_globals_then(|| { - let mi = dummy_meta_item_name_value("foo", kw::False, LitKind::Bool(false)); - assert!(Cfg::parse(&mi).is_err()); - - let mi = dummy_meta_item_list!(not, [a, b]); - assert!(Cfg::parse(&mi).is_err()); - - let mi = dummy_meta_item_list!(not, []); - assert!(Cfg::parse(&mi).is_err()); - - let mi = dummy_meta_item_list!(foo, []); - assert!(Cfg::parse(&mi).is_err()); - - let mi = dummy_meta_item_list!( - all, - [dummy_meta_item_list!(foo, []), dummy_meta_item_word("b"),] - ); - assert!(Cfg::parse(&mi).is_err()); - - let mi = dummy_meta_item_list!( - any, - [dummy_meta_item_word("a"), dummy_meta_item_list!(foo, []),] - ); - assert!(Cfg::parse(&mi).is_err()); - - let mi = dummy_meta_item_list!(not, [dummy_meta_item_list!(foo, []),]); - assert!(Cfg::parse(&mi).is_err()); - - let c = Symbol::intern("e"); - let mi = dummy_lit(c, LitKind::Char('e')); - assert!(Cfg::parse(&mi).is_err()); - - let five = Symbol::intern("5"); - let mi = dummy_lit(five, LitKind::Int(5.into(), LitIntType::Unsuffixed)); - assert!(Cfg::parse(&mi).is_err()); - }) -} - #[test] fn test_render_short_html() { create_default_session_globals_then(|| { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0768e6a56b3c..8de3722fa69d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -51,7 +51,7 @@ use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeVisitableE use rustc_middle::{bug, span_bug}; use rustc_span::ExpnKind; use rustc_span::hygiene::{AstPass, MacroKind}; -use rustc_span::symbol::{Ident, Symbol, kw, sym}; +use rustc_span::symbol::{Ident, Symbol, kw}; use rustc_trait_selection::traits::wf::object_region_bounds; use tracing::{debug, instrument}; use utils::*; @@ -2682,17 +2682,13 @@ fn add_without_unwanted_attributes<'hir>( import_parent, )); } - hir::Attribute::Unparsed(normal) if let [name] = &*normal.path.segments => { - if is_inline || *name != sym::cfg_trace { - // If it's not a `cfg()` attribute, we keep it. - attrs.push((Cow::Borrowed(attr), import_parent)); - } - } - // FIXME: make sure to exclude `#[cfg_trace]` here when it is ported to the new parsers - hir::Attribute::Parsed(..) => { + + // We discard `#[cfg(...)]` attributes unless we're inlining + hir::Attribute::Parsed(AttributeKind::CfgTrace(..)) if !is_inline => {} + // We keep all other attributes + _ => { attrs.push((Cow::Borrowed(attr), import_parent)); } - _ => {} } } } diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index d4bf74c29514..54da158d4d39 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -2,7 +2,6 @@ use rustc_hir::Attribute; use rustc_hir::attrs::{AttributeKind, DocAttribute}; -use rustc_span::symbol::sym; use crate::clean::inline::{load_attrs, merge_attrs}; use crate::clean::{CfgInfo, Crate, Item, ItemKind}; @@ -39,10 +38,7 @@ fn add_only_cfg_attributes(attrs: &mut Vec, new_attrs: &[Attribute]) let mut new_attr = DocAttribute::default(); new_attr.cfg = d.cfg.clone(); attrs.push(Attribute::Parsed(AttributeKind::Doc(Box::new(new_attr)))); - } else if let Attribute::Unparsed(normal) = attr - && let [name] = &*normal.path.segments - && *name == sym::cfg_trace - { + } else if let Attribute::Parsed(AttributeKind::CfgTrace(..)) = attr { // If it's a `cfg()` attribute, we keep it. attrs.push(attr.clone()); }