diff options
| author | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2023-12-15 11:51:23 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-12-15 11:51:23 +0100 |
| commit | ec0008a915c3d27528a2df0eb420aed748b217f8 (patch) | |
| tree | a56142d8f4e578b4b6064df07c49084271f32387 /src | |
| parent | d253bf61ad38a59cc579aee688f81a06c31283d3 (diff) | |
| parent | 823148fa849eb9b6fb896a0ac1772a2be3bdb043 (diff) | |
| download | rust-ec0008a915c3d27528a2df0eb420aed748b217f8.tar.gz rust-ec0008a915c3d27528a2df0eb420aed748b217f8.zip | |
Rollup merge of #113091 - GuillaumeGomez:prevent-cfg-merge-reexport, r=rustdoc
Don't merge cfg and doc(cfg) attributes for re-exports Fixes #112881. ## Explanations When re-exporting things with different `cfg`s there are two things that can happen: * The re-export uses a subset of `cfg`s, this subset is sufficient so that the item will appear exactly with the subset * The re-export uses a non-subset of `cfg`s (e.g. like the example I posted just above where the re-export is ungated), if the non-subset `cfg`s are active (e.g. compiling that example on windows) then this will be a compile error as the item doesn't exist to re-export, if the subset `cfg`s are active it behaves like 1. ### Glob re-exports? **This only applies to non-glob inlined re-exports.** For glob re-exports the item may or may not exist to be re-exported (potentially the `cfg`s on the path up until the glob can be removed, and only `cfg`s on the globbed item itself matter), for non-inlined re-exports see https://github.com/rust-lang/rust/issues/85043. cc `@Nemo157` r? `@notriddle`
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustdoc/clean/mod.rs | 76 | ||||
| -rw-r--r-- | src/librustdoc/html/render/print_item.rs | 13 |
2 files changed, 44 insertions, 45 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 28ea662eab3..6631c427270 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2646,6 +2646,40 @@ fn filter_tokens_from_list( tokens } +fn filter_doc_attr_ident(ident: Symbol, is_inline: bool) -> bool { + if is_inline { + ident == sym::hidden || ident == sym::inline || ident == sym::no_inline + } else { + ident == sym::cfg + } +} + +/// Remove attributes from `normal` that should not be inherited by `use` re-export. +/// Before calling this function, make sure `normal` is a `#[doc]` attribute. +fn filter_doc_attr(normal: &mut ast::NormalAttr, is_inline: bool) { + match normal.item.args { + ast::AttrArgs::Delimited(ref mut args) => { + let tokens = filter_tokens_from_list(&args.tokens, |token| { + !matches!( + token, + TokenTree::Token( + Token { + kind: TokenKind::Ident( + ident, + _, + ), + .. + }, + _, + ) if filter_doc_attr_ident(*ident, is_inline), + ) + }); + args.tokens = TokenStream::new(tokens); + } + ast::AttrArgs::Empty | ast::AttrArgs::Eq(..) => {} + } +} + /// When inlining items, we merge their attributes (and all the reexports attributes too) with the /// final reexport. For example: /// @@ -2672,13 +2706,6 @@ fn add_without_unwanted_attributes<'hir>( is_inline: bool, import_parent: Option<DefId>, ) { - // If it's not `#[doc(inline)]`, we don't want all attributes, otherwise we keep everything. - if !is_inline { - for attr in new_attrs { - attrs.push((Cow::Borrowed(attr), import_parent)); - } - return; - } for attr in new_attrs { if matches!(attr.kind, ast::AttrKind::DocComment(..)) { attrs.push((Cow::Borrowed(attr), import_parent)); @@ -2687,33 +2714,14 @@ fn add_without_unwanted_attributes<'hir>( let mut attr = attr.clone(); match attr.kind { ast::AttrKind::Normal(ref mut normal) => { - if let [ident] = &*normal.item.path.segments - && let ident = ident.ident.name - && ident == sym::doc - { - match normal.item.args { - ast::AttrArgs::Delimited(ref mut args) => { - let tokens = filter_tokens_from_list(&args.tokens, |token| { - !matches!( - token, - TokenTree::Token( - Token { - kind: TokenKind::Ident( - sym::hidden | sym::inline | sym::no_inline, - _, - ), - .. - }, - _, - ), - ) - }); - args.tokens = TokenStream::new(tokens); - attrs.push((Cow::Owned(attr), import_parent)); - } - ast::AttrArgs::Empty | ast::AttrArgs::Eq(..) => { - attrs.push((Cow::Owned(attr), import_parent)); - } + if let [ident] = &*normal.item.path.segments { + let ident = ident.ident.name; + if ident == sym::doc { + filter_doc_attr(normal, is_inline); + attrs.push((Cow::Owned(attr), import_parent)); + } else if ident != sym::cfg { + // If it's not a `cfg()` attribute, we keep it. + attrs.push((Cow::Owned(attr), import_parent)); } } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index ff7ce01e807..5ca623f01f1 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1,5 +1,3 @@ -use clean::AttributesExt; - use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; @@ -465,16 +463,9 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: clean::ImportItem(ref import) => { let stab_tags = if let Some(import_def_id) = import.source.did { - let ast_attrs = tcx.get_attrs_unchecked(import_def_id); - let import_attrs = Box::new(clean::Attributes::from_ast(ast_attrs)); - // Just need an item with the correct def_id and attrs - let import_item = clean::Item { - item_id: import_def_id.into(), - attrs: import_attrs, - cfg: ast_attrs.cfg(tcx, &cx.cache().hidden_cfg), - ..myitem.clone() - }; + let import_item = + clean::Item { item_id: import_def_id.into(), ..myitem.clone() }; let stab_tags = Some(extra_info_tags(&import_item, item, tcx).to_string()); stab_tags |
