@@ -2126,6 +2126,87 @@ fn get_all_import_attributes<'hir>(
21262126 }
21272127}
21282128
2129+ /// When inlining items, we merge its attributes (and all the reexports attributes too) with the
2130+ /// final reexport. For example:
2131+ ///
2132+ /// ```
2133+ /// #[doc(hidden, cfg(feature = "foo"))]
2134+ /// pub struct Foo;
2135+ ///
2136+ /// #[doc(cfg(feature = "bar"))]
2137+ /// #[doc(hidden, no_inline)]
2138+ /// pub use Foo as Foo1;
2139+ ///
2140+ /// #[doc(inline)]
2141+ /// pub use Foo2 as Bar;
2142+ /// ```
2143+ ///
2144+ /// So `Bar` at the end will have both `cfg(feature = "...")`. However, we don't want to merge all
2145+ /// attributes so we filter out the following ones:
2146+ /// * `doc(inline)`
2147+ /// * `doc(no_inline)`
2148+ /// * `doc(hidden)`
2149+ fn add_without_unwanted_attributes ( attrs : & mut Vec < ast:: Attribute > , new_attrs : & [ ast:: Attribute ] ) {
2150+ use rustc_ast:: token:: { Token , TokenKind } ;
2151+ use rustc_ast:: tokenstream:: { TokenStream , TokenTree } ;
2152+
2153+ for attr in new_attrs {
2154+ let mut attr = attr. clone ( ) ;
2155+ match attr. kind {
2156+ ast:: AttrKind :: Normal ( ref mut normal) => {
2157+ if let [ ident] = & * normal. item . path . segments {
2158+ let ident = ident. ident . name ;
2159+ if ident == sym:: doc {
2160+ match normal. item . args {
2161+ ast:: AttrArgs :: Delimited ( ref mut args) => {
2162+ let mut tokens = Vec :: with_capacity ( args. tokens . len ( ) ) ;
2163+ let mut skip_next_comma = false ;
2164+ for token in args. tokens . clone ( ) . into_trees ( ) {
2165+ match token {
2166+ TokenTree :: Token (
2167+ Token {
2168+ kind :
2169+ TokenKind :: Ident (
2170+ sym:: hidden | sym:: inline | sym:: no_inline,
2171+ _,
2172+ ) ,
2173+ ..
2174+ } ,
2175+ _,
2176+ ) => {
2177+ skip_next_comma = true ;
2178+ continue ;
2179+ }
2180+ TokenTree :: Token (
2181+ Token { kind : TokenKind :: Comma , .. } ,
2182+ _,
2183+ ) if skip_next_comma => {
2184+ skip_next_comma = false ;
2185+ continue ;
2186+ }
2187+ _ => { }
2188+ }
2189+ skip_next_comma = false ;
2190+ tokens. push ( token) ;
2191+ }
2192+ args. tokens = TokenStream :: new ( tokens) ;
2193+ attrs. push ( attr) ;
2194+ }
2195+ ast:: AttrArgs :: Empty | ast:: AttrArgs :: Eq ( ..) => {
2196+ attrs. push ( attr) ;
2197+ continue ;
2198+ }
2199+ }
2200+ }
2201+ }
2202+ }
2203+ ast:: AttrKind :: DocComment ( ..) => {
2204+ attrs. push ( attr) ;
2205+ }
2206+ }
2207+ }
2208+ }
2209+
21292210fn clean_maybe_renamed_item < ' tcx > (
21302211 cx : & mut DocContext < ' tcx > ,
21312212 item : & hir:: Item < ' tcx > ,
@@ -2216,17 +2297,17 @@ fn clean_maybe_renamed_item<'tcx>(
22162297 extra_attrs. extend_from_slice ( inline:: load_attrs ( cx, import_id. to_def_id ( ) ) ) ;
22172298 // Then we get all the various imports' attributes.
22182299 get_all_import_attributes ( use_node, cx. tcx , item. owner_id . def_id , & mut extra_attrs) ;
2300+ add_without_unwanted_attributes ( & mut extra_attrs, inline:: load_attrs ( cx, def_id) ) ;
2301+ } else {
2302+ // We only keep the item's attributes.
2303+ extra_attrs. extend_from_slice ( inline:: load_attrs ( cx, def_id) ) ;
22192304 }
22202305
2221- let mut item = if !extra_attrs. is_empty ( ) {
2222- extra_attrs. extend_from_slice ( inline:: load_attrs ( cx, def_id) ) ;
2223- let attrs = Attributes :: from_ast ( & extra_attrs) ;
2224- let cfg = extra_attrs. cfg ( cx. tcx , & cx. cache . hidden_cfg ) ;
2306+ let attrs = Attributes :: from_ast ( & extra_attrs) ;
2307+ let cfg = extra_attrs. cfg ( cx. tcx , & cx. cache . hidden_cfg ) ;
22252308
2226- Item :: from_def_id_and_attrs_and_parts ( def_id, Some ( name) , kind, Box :: new ( attrs) , cfg)
2227- } else {
2228- Item :: from_def_id_and_parts ( def_id, Some ( name) , kind, cx)
2229- } ;
2309+ let mut item =
2310+ Item :: from_def_id_and_attrs_and_parts ( def_id, Some ( name) , kind, Box :: new ( attrs) , cfg) ;
22302311 item. inline_stmt_id = import_id. map ( |def_id| def_id. to_def_id ( ) ) ;
22312312 vec ! [ item]
22322313 } )
0 commit comments