Skip to content

Commit 709525f

Browse files
Fix doc(auto_cfg) attribute parsing
1 parent 33d0327 commit 709525f

File tree

3 files changed

+82
-101
lines changed

3 files changed

+82
-101
lines changed

compiler/rustc_attr_parsing/src/attributes/doc.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,21 @@ impl DocParser {
224224
cx: &'c mut AcceptContext<'_, '_, S>,
225225
args: &ArgParser<'_>,
226226
) {
227-
if let Some(cfg_entry) = super::cfg::parse_cfg(cx, args) {
227+
// This function replaces cases like `cfg(all())` with `true`.
228+
fn simplify_cfg(cfg_entry: &mut CfgEntry) {
229+
match cfg_entry {
230+
CfgEntry::All(cfgs, span) if cfgs.is_empty() => {
231+
*cfg_entry = CfgEntry::Bool(true, *span)
232+
}
233+
CfgEntry::Any(cfgs, span) if cfgs.is_empty() => {
234+
*cfg_entry = CfgEntry::Bool(false, *span)
235+
}
236+
CfgEntry::Not(cfg, _) => simplify_cfg(cfg),
237+
_ => {}
238+
}
239+
}
240+
if let Some(mut cfg_entry) = super::cfg::parse_cfg(cx, args) {
241+
simplify_cfg(&mut cfg_entry);
228242
self.attribute.cfg.push(cfg_entry);
229243
}
230244
}
@@ -237,7 +251,7 @@ impl DocParser {
237251
) {
238252
match args {
239253
ArgParser::NoArgs => {
240-
cx.expected_list(args.span().unwrap_or(path.span()));
254+
self.attribute.auto_cfg_change.push((true, path.span()));
241255
}
242256
ArgParser::List(list) => {
243257
for meta in list.mixed() {
@@ -303,6 +317,7 @@ impl DocParser {
303317
}
304318
}
305319
}
320+
self.attribute.auto_cfg.push((cfg_hide_show, path.span()));
306321
}
307322
}
308323
ArgParser::NameValue(nv) => {
@@ -311,7 +326,7 @@ impl DocParser {
311326
cx.emit_lint(AttributeLintKind::DocAutoCfgWrongLiteral, nv.value_span);
312327
return;
313328
};
314-
self.attribute.auto_cfg_change = Some((*bool_value, *span));
329+
self.attribute.auto_cfg_change.push((*bool_value, *span));
315330
}
316331
}
317332
}
@@ -524,9 +539,6 @@ impl<S: Stage> AttributeParser<S> for DocParser {
524539

525540
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
526541
if self.nb_doc_attrs != 0 {
527-
if std::env::var("LOL").is_ok() {
528-
eprintln!("+++++> {:#?}", self.attribute);
529-
}
530542
Some(AttributeKind::Doc(Box::new(self.attribute)))
531543
} else {
532544
None

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -480,9 +480,9 @@ pub struct DocAttribute {
480480

481481
// unstable
482482
pub cfg: ThinVec<CfgEntry>,
483-
pub auto_cfg: ThinVec<CfgHideShow>,
484-
/// This is for `#[doc(auto_cfg = false|true)]`.
485-
pub auto_cfg_change: Option<(bool, Span)>,
483+
pub auto_cfg: ThinVec<(CfgHideShow, Span)>,
484+
/// This is for `#[doc(auto_cfg = false|true)]`/`#[doc(auto_cfg)]`.
485+
pub auto_cfg_change: ThinVec<(bool, Span)>,
486486

487487
// builtin
488488
pub fake_variadic: Option<Span>,
@@ -514,7 +514,7 @@ impl Default for DocAttribute {
514514
inline: None,
515515
cfg: ThinVec::new(),
516516
auto_cfg: ThinVec::new(),
517-
auto_cfg_change: None,
517+
auto_cfg_change: ThinVec::new(),
518518
fake_variadic: None,
519519
keyword: None,
520520
attribute: None,

src/librustdoc/clean/cfg.rs

Lines changed: 60 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ use itertools::Either;
1010
use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit};
1111
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1212
use rustc_data_structures::thin_vec::{ThinVec, thin_vec};
13+
use rustc_hir as hir;
1314
use rustc_hir::Attribute;
14-
use rustc_hir::attrs::{AttributeKind, CfgEntry};
15+
use rustc_hir::attrs::{self, AttributeKind, CfgEntry, CfgHideShow, HideOrShow};
1516
use rustc_middle::ty::TyCtxt;
1617
use rustc_session::parse::ParseSess;
1718
use rustc_span::symbol::{Symbol, sym};
1819
use rustc_span::{DUMMY_SP, Span};
19-
use {rustc_ast as ast, rustc_hir as hir};
2020

2121
use crate::display::{Joined as _, MaybeDisplay, Wrapped};
2222
use crate::html::escape::Escape;
@@ -689,6 +689,12 @@ impl<'a> From<&'a CfgEntry> for SimpleCfg {
689689
}
690690
}
691691

692+
impl<'a> From<&'a attrs::CfgInfo> for SimpleCfg {
693+
fn from(cfg: &'a attrs::CfgInfo) -> Self {
694+
Self { name: cfg.name, value: cfg.value.map(|(value, _)| value) }
695+
}
696+
}
697+
692698
/// This type keeps track of (doc) cfg information as we go down the item tree.
693699
#[derive(Clone, Debug)]
694700
pub(crate) struct CfgInfo {
@@ -746,37 +752,27 @@ fn show_hide_show_conflict_error(
746752
fn handle_auto_cfg_hide_show(
747753
tcx: TyCtxt<'_>,
748754
cfg_info: &mut CfgInfo,
749-
sub_attr: &MetaItemInner,
750-
is_show: bool,
755+
attr: &CfgHideShow,
756+
attr_span: Span,
751757
new_show_attrs: &mut FxHashMap<(Symbol, Option<Symbol>), rustc_span::Span>,
752758
new_hide_attrs: &mut FxHashMap<(Symbol, Option<Symbol>), rustc_span::Span>,
753759
) {
754-
if let MetaItemInner::MetaItem(item) = sub_attr
755-
&& let MetaItemKind::List(items) = &item.kind
756-
{
757-
for item in items {
758-
// FIXME: Report in case `Cfg::parse` reports an error?
759-
760-
let Ok(cfg) = Cfg::parse(item) else { continue };
761-
if let CfgEntry::NameValue { name, value, .. } = cfg.0 {
762-
let value = value.map(|(v, _)| v);
763-
let simple = SimpleCfg::from(&cfg.0);
764-
if is_show {
765-
if let Some(span) = new_hide_attrs.get(&(name, value)) {
766-
show_hide_show_conflict_error(tcx, item.span(), *span);
767-
} else {
768-
new_show_attrs.insert((name, value), item.span());
769-
}
770-
cfg_info.hidden_cfg.remove(&simple);
771-
} else {
772-
if let Some(span) = new_show_attrs.get(&(name, value)) {
773-
show_hide_show_conflict_error(tcx, item.span(), *span);
774-
} else {
775-
new_hide_attrs.insert((name, value), item.span());
776-
}
777-
cfg_info.hidden_cfg.insert(simple);
778-
}
760+
for value in &attr.values {
761+
let simple = SimpleCfg::from(value);
762+
if attr.kind == HideOrShow::Show {
763+
if let Some(span) = new_hide_attrs.get(&(simple.name, simple.value)) {
764+
show_hide_show_conflict_error(tcx, attr_span, *span);
765+
} else {
766+
new_show_attrs.insert((simple.name, simple.value), attr_span);
779767
}
768+
cfg_info.hidden_cfg.remove(&simple);
769+
} else {
770+
if let Some(span) = new_show_attrs.get(&(simple.name, simple.value)) {
771+
show_hide_show_conflict_error(tcx, attr_span, *span);
772+
} else {
773+
new_hide_attrs.insert((simple.name, simple.value), attr_span);
774+
}
775+
cfg_info.hidden_cfg.insert(simple);
780776
}
781777
}
782778
}
@@ -797,7 +793,7 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
797793

798794
fn check_changed_auto_active_status(
799795
changed_auto_active_status: &mut Option<rustc_span::Span>,
800-
attr: &ast::MetaItem,
796+
attr_span: Span,
801797
cfg_info: &mut CfgInfo,
802798
tcx: TyCtxt<'_>,
803799
new_value: bool,
@@ -807,14 +803,14 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
807803
tcx.sess
808804
.dcx()
809805
.struct_span_err(
810-
vec![*first_change, attr.span],
806+
vec![*first_change, attr_span],
811807
"`auto_cfg` was disabled and enabled more than once on the same item",
812808
)
813809
.emit();
814810
return true;
815811
}
816812
} else {
817-
*changed_auto_active_status = Some(attr.span);
813+
*changed_auto_active_status = Some(attr_span);
818814
}
819815
cfg_info.auto_cfg_active = new_value;
820816
false
@@ -826,7 +822,7 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
826822
let mut doc_cfg = attrs
827823
.clone()
828824
.filter_map(|attr| match attr {
829-
Attribute::Parsed(AttributeKind::Doc(d)) => Some(d),
825+
Attribute::Parsed(AttributeKind::Doc(d)) if !d.cfg.is_empty() => Some(d),
830826
_ => None,
831827
})
832828
.peekable();
@@ -850,64 +846,37 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
850846

851847
// We get all `doc(auto_cfg)`, `cfg` and `target_feature` attributes.
852848
for attr in attrs {
853-
if let Some(ident) = attr.ident()
854-
&& ident.name == sym::doc
855-
&& let Some(attrs) = attr.meta_item_list()
856-
{
857-
for attr in attrs.iter().filter(|attr| attr.has_name(sym::auto_cfg)) {
858-
let MetaItemInner::MetaItem(attr) = attr else {
859-
continue;
860-
};
861-
match &attr.kind {
862-
MetaItemKind::Word => {
863-
if check_changed_auto_active_status(
864-
&mut changed_auto_active_status,
865-
attr,
866-
cfg_info,
867-
tcx,
868-
true,
869-
) {
870-
return None;
871-
}
872-
}
873-
MetaItemKind::NameValue(lit) => {
874-
if let LitKind::Bool(value) = lit.kind {
875-
if check_changed_auto_active_status(
876-
&mut changed_auto_active_status,
877-
attr,
878-
cfg_info,
879-
tcx,
880-
value,
881-
) {
882-
return None;
883-
}
884-
}
885-
}
886-
MetaItemKind::List(sub_attrs) => {
887-
if check_changed_auto_active_status(
888-
&mut changed_auto_active_status,
889-
attr,
890-
cfg_info,
891-
tcx,
892-
true,
893-
) {
894-
return None;
895-
}
896-
for sub_attr in sub_attrs.iter() {
897-
if let Some(ident) = sub_attr.ident()
898-
&& (ident.name == sym::show || ident.name == sym::hide)
899-
{
900-
handle_auto_cfg_hide_show(
901-
tcx,
902-
cfg_info,
903-
&sub_attr,
904-
ident.name == sym::show,
905-
&mut new_show_attrs,
906-
&mut new_hide_attrs,
907-
);
908-
}
909-
}
910-
}
849+
if let Attribute::Parsed(AttributeKind::Doc(d)) = attr {
850+
for (new_value, span) in &d.auto_cfg_change {
851+
if check_changed_auto_active_status(
852+
&mut changed_auto_active_status,
853+
*span,
854+
cfg_info,
855+
tcx,
856+
*new_value,
857+
) {
858+
return None;
859+
}
860+
}
861+
if let Some((_, span)) = d.auto_cfg.first() {
862+
if check_changed_auto_active_status(
863+
&mut changed_auto_active_status,
864+
*span,
865+
cfg_info,
866+
tcx,
867+
true,
868+
) {
869+
return None;
870+
}
871+
for (value, span) in &d.auto_cfg {
872+
handle_auto_cfg_hide_show(
873+
tcx,
874+
cfg_info,
875+
value,
876+
*span,
877+
&mut new_show_attrs,
878+
&mut new_hide_attrs,
879+
);
911880
}
912881
}
913882
} else if let hir::Attribute::Parsed(AttributeKind::TargetFeature { features, .. }) = attr {

0 commit comments

Comments
 (0)