Skip to content

Commit 4429814

Browse files
Convert librustdoc to use the new parsed representation
1 parent 5590fc0 commit 4429814

4 files changed

Lines changed: 11 additions & 273 deletions

File tree

src/librustdoc/clean/cfg.rs

Lines changed: 4 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use std::sync::Arc;
77
use std::{fmt, mem, ops};
88

99
use itertools::Either;
10-
use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit};
1110
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1211
use rustc_data_structures::thin_vec::{ThinVec, thin_vec};
1312
use rustc_hir as hir;
@@ -29,12 +28,6 @@ mod tests;
2928
#[cfg_attr(test, derive(PartialEq))]
3029
pub(crate) struct Cfg(CfgEntry);
3130

32-
#[derive(PartialEq, Debug)]
33-
pub(crate) struct InvalidCfgError {
34-
pub(crate) msg: &'static str,
35-
pub(crate) span: Span,
36-
}
37-
3831
/// Whether the configuration consists of just `Cfg` or `Not`.
3932
fn is_simple_cfg(cfg: &CfgEntry) -> bool {
4033
match cfg {
@@ -105,106 +98,6 @@ fn should_capitalize_first_letter(cfg: &CfgEntry) -> bool {
10598
}
10699

107100
impl Cfg {
108-
/// Parses a `MetaItemInner` into a `Cfg`.
109-
fn parse_nested(
110-
nested_cfg: &MetaItemInner,
111-
exclude: &FxHashSet<NameValueCfg>,
112-
) -> Result<Option<Cfg>, InvalidCfgError> {
113-
match nested_cfg {
114-
MetaItemInner::MetaItem(cfg) => Cfg::parse_without(cfg, exclude),
115-
MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => {
116-
Ok(Some(Cfg(CfgEntry::Bool(*b, DUMMY_SP))))
117-
}
118-
MetaItemInner::Lit(lit) => {
119-
Err(InvalidCfgError { msg: "unexpected literal", span: lit.span })
120-
}
121-
}
122-
}
123-
124-
fn parse_without(
125-
cfg: &MetaItem,
126-
exclude: &FxHashSet<NameValueCfg>,
127-
) -> Result<Option<Cfg>, InvalidCfgError> {
128-
let name = match cfg.ident() {
129-
Some(ident) => ident.name,
130-
None => {
131-
return Err(InvalidCfgError {
132-
msg: "expected a single identifier",
133-
span: cfg.span,
134-
});
135-
}
136-
};
137-
match cfg.kind {
138-
MetaItemKind::Word => {
139-
if exclude.contains(&NameValueCfg::new(name)) {
140-
Ok(None)
141-
} else {
142-
Ok(Some(Cfg(CfgEntry::NameValue { name, value: None, span: DUMMY_SP })))
143-
}
144-
}
145-
MetaItemKind::NameValue(ref lit) => match lit.kind {
146-
LitKind::Str(value, _) => {
147-
if exclude.contains(&NameValueCfg::new_value(name, value)) {
148-
Ok(None)
149-
} else {
150-
Ok(Some(Cfg(CfgEntry::NameValue {
151-
name,
152-
value: Some(value),
153-
span: DUMMY_SP,
154-
})))
155-
}
156-
}
157-
_ => Err(InvalidCfgError {
158-
// FIXME: if the main #[cfg] syntax decided to support non-string literals,
159-
// this should be changed as well.
160-
msg: "value of cfg option should be a string literal",
161-
span: lit.span,
162-
}),
163-
},
164-
MetaItemKind::List(ref items) => {
165-
let orig_len = items.len();
166-
let mut sub_cfgs =
167-
items.iter().filter_map(|i| Cfg::parse_nested(i, exclude).transpose());
168-
let ret = match name {
169-
sym::all => {
170-
sub_cfgs.try_fold(Cfg(CfgEntry::Bool(true, DUMMY_SP)), |x, y| Ok(x & y?))
171-
}
172-
sym::any => {
173-
sub_cfgs.try_fold(Cfg(CfgEntry::Bool(false, DUMMY_SP)), |x, y| Ok(x | y?))
174-
}
175-
sym::not => {
176-
if orig_len == 1 {
177-
let mut sub_cfgs = sub_cfgs.collect::<Vec<_>>();
178-
if sub_cfgs.len() == 1 {
179-
Ok(!sub_cfgs.pop().unwrap()?)
180-
} else {
181-
return Ok(None);
182-
}
183-
} else {
184-
Err(InvalidCfgError { msg: "expected 1 cfg-pattern", span: cfg.span })
185-
}
186-
}
187-
_ => Err(InvalidCfgError { msg: "invalid predicate", span: cfg.span }),
188-
};
189-
match ret {
190-
Ok(c) => Ok(Some(c)),
191-
Err(e) => Err(e),
192-
}
193-
}
194-
}
195-
}
196-
197-
/// Parses a `MetaItem` into a `Cfg`.
198-
///
199-
/// The `MetaItem` should be the content of the `#[cfg(...)]`, e.g., `unix` or
200-
/// `target_os = "redox"`.
201-
///
202-
/// If the content is not properly formatted, it will return an error indicating what and where
203-
/// the error is.
204-
pub(crate) fn parse(cfg: &MetaItemInner) -> Result<Cfg, InvalidCfgError> {
205-
Self::parse_nested(cfg, &FxHashSet::default()).map(|ret| ret.unwrap())
206-
}
207-
208101
/// Renders the configuration for human display, as a short HTML description.
209102
pub(crate) fn render_short_html(&self) -> String {
210103
let mut msg = Display(&self.0, Format::ShortHtml).to_string();
@@ -644,10 +537,6 @@ impl NameValueCfg {
644537
fn new(name: Symbol) -> Self {
645538
Self { name, value: None }
646539
}
647-
648-
fn new_value(name: Symbol, value: Symbol) -> Self {
649-
Self { name, value: Some(value) }
650-
}
651540
}
652541

653542
impl<'a> From<&'a CfgEntry> for NameValueCfg {
@@ -751,15 +640,6 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
751640
tcx: TyCtxt<'_>,
752641
cfg_info: &mut CfgInfo,
753642
) -> Option<Arc<Cfg>> {
754-
fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
755-
let mut iter = it.into_iter();
756-
let item = iter.next()?;
757-
if iter.next().is_some() {
758-
return None;
759-
}
760-
Some(item)
761-
}
762-
763643
fn check_changed_auto_active_status(
764644
changed_auto_active_status: &mut Option<rustc_span::Span>,
765645
attr_span: Span,
@@ -859,12 +739,11 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
859739
}
860740
continue;
861741
} else if !cfg_info.parent_is_doc_cfg
862-
&& let Some(name) = attr.name()
863-
&& matches!(name, sym::cfg | sym::cfg_trace)
864-
&& let Some(attr) = single(attr.meta_item_list()?)
865-
&& let Ok(new_cfg) = Cfg::parse(&attr)
742+
&& let hir::Attribute::Parsed(AttributeKind::CfgTrace(cfgs)) = attr
866743
{
867-
cfg_info.current_cfg &= new_cfg;
744+
for (new_cfg, _) in cfgs {
745+
cfg_info.current_cfg &= Cfg(new_cfg.clone());
746+
}
868747
}
869748
}
870749

src/librustdoc/clean/cfg/tests.rs

Lines changed: 0 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
use rustc_ast::ast::LitIntType;
2-
use rustc_ast::{MetaItemInner, MetaItemLit, Path, Safety, StrStyle};
31
use rustc_data_structures::thin_vec::thin_vec;
42
use rustc_hir::attrs::CfgEntry;
5-
use rustc_span::symbol::{Ident, kw};
63
use rustc_span::{DUMMY_SP, create_default_session_globals_then};
74

85
use super::*;
@@ -28,10 +25,6 @@ fn name_value_cfg_e(name: &str, value: &str) -> CfgEntry {
2825
}
2926
}
3027

31-
fn dummy_lit(symbol: Symbol, kind: LitKind) -> MetaItemInner {
32-
MetaItemInner::Lit(MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP })
33-
}
34-
3528
fn cfg_all(v: ThinVec<CfgEntry>) -> Cfg {
3629
Cfg(cfg_all_e(v))
3730
}
@@ -52,51 +45,6 @@ fn cfg_not(v: CfgEntry) -> Cfg {
5245
Cfg(CfgEntry::Not(Box::new(v), DUMMY_SP))
5346
}
5447

55-
fn dummy_meta_item_word(name: &str) -> MetaItemInner {
56-
MetaItemInner::MetaItem(MetaItem {
57-
unsafety: Safety::Default,
58-
path: Path::from_ident(Ident::from_str(name)),
59-
kind: MetaItemKind::Word,
60-
span: DUMMY_SP,
61-
})
62-
}
63-
64-
fn dummy_meta_item_name_value(name: &str, symbol: Symbol, kind: LitKind) -> MetaItemInner {
65-
let lit = MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP };
66-
MetaItemInner::MetaItem(MetaItem {
67-
unsafety: Safety::Default,
68-
path: Path::from_ident(Ident::from_str(name)),
69-
kind: MetaItemKind::NameValue(lit),
70-
span: DUMMY_SP,
71-
})
72-
}
73-
74-
macro_rules! dummy_meta_item_list {
75-
($name:ident, [$($list:ident),* $(,)?]) => {
76-
MetaItemInner::MetaItem(MetaItem {
77-
unsafety: Safety::Default,
78-
path: Path::from_ident(Ident::from_str(stringify!($name))),
79-
kind: MetaItemKind::List(thin_vec![
80-
$(
81-
dummy_meta_item_word(stringify!($list)),
82-
)*
83-
]),
84-
span: DUMMY_SP,
85-
})
86-
};
87-
88-
($name:ident, [$($list:expr),* $(,)?]) => {
89-
MetaItemInner::MetaItem(MetaItem {
90-
unsafety: Safety::Default,
91-
path: Path::from_ident(Ident::from_str(stringify!($name))),
92-
kind: MetaItemKind::List(thin_vec![
93-
$($list,)*
94-
]),
95-
span: DUMMY_SP,
96-
})
97-
};
98-
}
99-
10048
fn cfg_true() -> Cfg {
10149
Cfg(CfgEntry::Bool(true, DUMMY_SP))
10250
}
@@ -303,87 +251,6 @@ fn test_cfg_or() {
303251
})
304252
}
305253

306-
#[test]
307-
fn test_parse_ok() {
308-
create_default_session_globals_then(|| {
309-
let r#true = Symbol::intern("true");
310-
let mi = dummy_lit(r#true, LitKind::Bool(true));
311-
assert_eq!(Cfg::parse(&mi), Ok(cfg_true()));
312-
313-
let r#false = Symbol::intern("false");
314-
let mi = dummy_lit(r#false, LitKind::Bool(false));
315-
assert_eq!(Cfg::parse(&mi), Ok(cfg_false()));
316-
317-
let mi = dummy_meta_item_word("all");
318-
assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all")));
319-
320-
let done = Symbol::intern("done");
321-
let mi = dummy_meta_item_name_value("all", done, LitKind::Str(done, StrStyle::Cooked));
322-
assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done")));
323-
324-
let mi = dummy_meta_item_list!(all, [a, b]);
325-
assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") & word_cfg("b")));
326-
327-
let mi = dummy_meta_item_list!(any, [a, b]);
328-
assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") | word_cfg("b")));
329-
330-
let mi = dummy_meta_item_list!(not, [a]);
331-
assert_eq!(Cfg::parse(&mi), Ok(!word_cfg("a")));
332-
333-
let mi = dummy_meta_item_list!(
334-
not,
335-
[dummy_meta_item_list!(
336-
any,
337-
[dummy_meta_item_word("a"), dummy_meta_item_list!(all, [b, c]),]
338-
),]
339-
);
340-
assert_eq!(Cfg::parse(&mi), Ok(!(word_cfg("a") | (word_cfg("b") & word_cfg("c")))));
341-
342-
let mi = dummy_meta_item_list!(all, [a, b, c]);
343-
assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") & word_cfg("b") & word_cfg("c")));
344-
})
345-
}
346-
347-
#[test]
348-
fn test_parse_err() {
349-
create_default_session_globals_then(|| {
350-
let mi = dummy_meta_item_name_value("foo", kw::False, LitKind::Bool(false));
351-
assert!(Cfg::parse(&mi).is_err());
352-
353-
let mi = dummy_meta_item_list!(not, [a, b]);
354-
assert!(Cfg::parse(&mi).is_err());
355-
356-
let mi = dummy_meta_item_list!(not, []);
357-
assert!(Cfg::parse(&mi).is_err());
358-
359-
let mi = dummy_meta_item_list!(foo, []);
360-
assert!(Cfg::parse(&mi).is_err());
361-
362-
let mi = dummy_meta_item_list!(
363-
all,
364-
[dummy_meta_item_list!(foo, []), dummy_meta_item_word("b"),]
365-
);
366-
assert!(Cfg::parse(&mi).is_err());
367-
368-
let mi = dummy_meta_item_list!(
369-
any,
370-
[dummy_meta_item_word("a"), dummy_meta_item_list!(foo, []),]
371-
);
372-
assert!(Cfg::parse(&mi).is_err());
373-
374-
let mi = dummy_meta_item_list!(not, [dummy_meta_item_list!(foo, []),]);
375-
assert!(Cfg::parse(&mi).is_err());
376-
377-
let c = Symbol::intern("e");
378-
let mi = dummy_lit(c, LitKind::Char('e'));
379-
assert!(Cfg::parse(&mi).is_err());
380-
381-
let five = Symbol::intern("5");
382-
let mi = dummy_lit(five, LitKind::Int(5.into(), LitIntType::Unsuffixed));
383-
assert!(Cfg::parse(&mi).is_err());
384-
})
385-
}
386-
387254
#[test]
388255
fn test_render_short_html() {
389256
create_default_session_globals_then(|| {

src/librustdoc/clean/mod.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeVisitableE
5151
use rustc_middle::{bug, span_bug};
5252
use rustc_span::ExpnKind;
5353
use rustc_span::hygiene::{AstPass, MacroKind};
54-
use rustc_span::symbol::{Ident, Symbol, kw, sym};
54+
use rustc_span::symbol::{Ident, Symbol, kw};
5555
use rustc_trait_selection::traits::wf::object_region_bounds;
5656
use tracing::{debug, instrument};
5757
use utils::*;
@@ -2682,17 +2682,13 @@ fn add_without_unwanted_attributes<'hir>(
26822682
import_parent,
26832683
));
26842684
}
2685-
hir::Attribute::Unparsed(normal) if let [name] = &*normal.path.segments => {
2686-
if is_inline || *name != sym::cfg_trace {
2687-
// If it's not a `cfg()` attribute, we keep it.
2688-
attrs.push((Cow::Borrowed(attr), import_parent));
2689-
}
2690-
}
2691-
// FIXME: make sure to exclude `#[cfg_trace]` here when it is ported to the new parsers
2692-
hir::Attribute::Parsed(..) => {
2685+
2686+
// We discard `#[cfg(...)]` attributes unless we're inlining
2687+
hir::Attribute::Parsed(AttributeKind::CfgTrace(..)) if !is_inline => {}
2688+
// We keep all other attributes
2689+
_ => {
26932690
attrs.push((Cow::Borrowed(attr), import_parent));
26942691
}
2695-
_ => {}
26962692
}
26972693
}
26982694
}

src/librustdoc/passes/propagate_doc_cfg.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
use rustc_hir::Attribute;
44
use rustc_hir::attrs::{AttributeKind, DocAttribute};
5-
use rustc_span::symbol::sym;
65

76
use crate::clean::inline::{load_attrs, merge_attrs};
87
use crate::clean::{CfgInfo, Crate, Item, ItemKind};
@@ -39,10 +38,7 @@ fn add_only_cfg_attributes(attrs: &mut Vec<Attribute>, new_attrs: &[Attribute])
3938
let mut new_attr = DocAttribute::default();
4039
new_attr.cfg = d.cfg.clone();
4140
attrs.push(Attribute::Parsed(AttributeKind::Doc(Box::new(new_attr))));
42-
} else if let Attribute::Unparsed(normal) = attr
43-
&& let [name] = &*normal.path.segments
44-
&& *name == sym::cfg_trace
45-
{
41+
} else if let Attribute::Parsed(AttributeKind::CfgTrace(..)) = attr {
4642
// If it's a `cfg()` attribute, we keep it.
4743
attrs.push(attr.clone());
4844
}

0 commit comments

Comments
 (0)