Auto merge of #84494 - tdelabro:84304-bis, r=jyn514
84304 - rustdoc: shrink Item::Attributes Helps with https://github.com/rust-lang/rust/issues/84304
This commit is contained in:
commit
727d101561
16 changed files with 158 additions and 128 deletions
|
@ -126,6 +126,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||||
synthetic: true,
|
synthetic: true,
|
||||||
blanket_impl: None,
|
blanket_impl: None,
|
||||||
}),
|
}),
|
||||||
|
cfg: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
|
||||||
synthetic: false,
|
synthetic: false,
|
||||||
blanket_impl: Some(trait_ref.self_ty().clean(self.cx)),
|
blanket_impl: Some(trait_ref.self_ty().clean(self.cx)),
|
||||||
}),
|
}),
|
||||||
|
cfg: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! Support for inlining external documentation into the current AST.
|
//! Support for inlining external documentation into the current AST.
|
||||||
|
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
|
@ -14,7 +15,7 @@ use rustc_span::hygiene::MacroKind;
|
||||||
use rustc_span::symbol::{kw, sym, Symbol};
|
use rustc_span::symbol::{kw, sym, Symbol};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
use crate::clean::{self, Attributes, GetDefId, ToSource};
|
use crate::clean::{self, Attributes, AttributesExt, GetDefId, ToSource};
|
||||||
use crate::core::DocContext;
|
use crate::core::DocContext;
|
||||||
use crate::formats::item_type::ItemType;
|
use crate::formats::item_type::ItemType;
|
||||||
|
|
||||||
|
@ -119,12 +120,16 @@ crate fn try_inline(
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let target_attrs = load_attrs(cx, did);
|
let (attrs, cfg) = merge_attrs(cx, Some(parent_module), load_attrs(cx, did), attrs_clone);
|
||||||
let attrs = box merge_attrs(cx, Some(parent_module), target_attrs, attrs_clone);
|
|
||||||
|
|
||||||
cx.inlined.insert(did);
|
cx.inlined.insert(did);
|
||||||
let what_rustc_thinks = clean::Item::from_def_id_and_parts(did, Some(name), kind, cx);
|
ret.push(clean::Item::from_def_id_and_attrs_and_parts(
|
||||||
ret.push(clean::Item { attrs, ..what_rustc_thinks });
|
did,
|
||||||
|
Some(name),
|
||||||
|
kind,
|
||||||
|
box attrs,
|
||||||
|
cx,
|
||||||
|
cfg,
|
||||||
|
));
|
||||||
Some(ret)
|
Some(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,22 +293,24 @@ fn merge_attrs(
|
||||||
parent_module: Option<DefId>,
|
parent_module: Option<DefId>,
|
||||||
old_attrs: Attrs<'_>,
|
old_attrs: Attrs<'_>,
|
||||||
new_attrs: Option<Attrs<'_>>,
|
new_attrs: Option<Attrs<'_>>,
|
||||||
) -> clean::Attributes {
|
) -> (clean::Attributes, Option<Arc<clean::cfg::Cfg>>) {
|
||||||
// NOTE: If we have additional attributes (from a re-export),
|
// NOTE: If we have additional attributes (from a re-export),
|
||||||
// always insert them first. This ensure that re-export
|
// always insert them first. This ensure that re-export
|
||||||
// doc comments show up before the original doc comments
|
// doc comments show up before the original doc comments
|
||||||
// when we render them.
|
// when we render them.
|
||||||
if let Some(inner) = new_attrs {
|
if let Some(inner) = new_attrs {
|
||||||
if let Some(new_id) = parent_module {
|
|
||||||
let diag = cx.sess().diagnostic();
|
|
||||||
Attributes::from_ast(diag, old_attrs, Some((inner, new_id)))
|
|
||||||
} else {
|
|
||||||
let mut both = inner.to_vec();
|
let mut both = inner.to_vec();
|
||||||
both.extend_from_slice(old_attrs);
|
both.extend_from_slice(old_attrs);
|
||||||
both.clean(cx)
|
(
|
||||||
}
|
if let Some(new_id) = parent_module {
|
||||||
|
Attributes::from_ast(old_attrs, Some((inner, new_id)))
|
||||||
} else {
|
} else {
|
||||||
old_attrs.clean(cx)
|
Attributes::from_ast(&both, None)
|
||||||
|
},
|
||||||
|
both.cfg(cx.sess().diagnostic()),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(old_attrs.clean(cx), old_attrs.cfg(cx.sess().diagnostic()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,8 +421,8 @@ crate fn build_impl(
|
||||||
|
|
||||||
debug!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id());
|
debug!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id());
|
||||||
|
|
||||||
let attrs = box merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs);
|
let (merged_attrs, cfg) = merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs);
|
||||||
debug!("merged_attrs={:?}", attrs);
|
debug!("merged_attrs={:?}", merged_attrs);
|
||||||
|
|
||||||
ret.push(clean::Item::from_def_id_and_attrs_and_parts(
|
ret.push(clean::Item::from_def_id_and_attrs_and_parts(
|
||||||
did,
|
did,
|
||||||
|
@ -432,8 +439,9 @@ crate fn build_impl(
|
||||||
synthetic: false,
|
synthetic: false,
|
||||||
blanket_impl: None,
|
blanket_impl: None,
|
||||||
}),
|
}),
|
||||||
attrs,
|
box merged_attrs,
|
||||||
cx,
|
cx,
|
||||||
|
cfg,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,6 +487,7 @@ fn build_module(
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
)),
|
)),
|
||||||
|
cfg: None,
|
||||||
});
|
});
|
||||||
} else if let Some(i) = try_inline(cx, did, item.res, item.ident.name, None, visited) {
|
} else if let Some(i) = try_inline(cx, did, item.res, item.ident.name, None, visited) {
|
||||||
items.extend(i)
|
items.extend(i)
|
||||||
|
|
|
@ -84,9 +84,8 @@ impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clean<ExternalCrate> for CrateNum {
|
impl Clean<ExternalCrate> for CrateNum {
|
||||||
fn clean(&self, cx: &mut DocContext<'_>) -> ExternalCrate {
|
fn clean(&self, _cx: &mut DocContext<'_>) -> ExternalCrate {
|
||||||
let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
|
ExternalCrate { crate_num: *self }
|
||||||
ExternalCrate { crate_num: *self, attrs: cx.tcx.get_attrs(root).clean(cx) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,8 +122,8 @@ impl Clean<Item> for doctree::Module<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clean<Attributes> for [ast::Attribute] {
|
impl Clean<Attributes> for [ast::Attribute] {
|
||||||
fn clean(&self, cx: &mut DocContext<'_>) -> Attributes {
|
fn clean(&self, _cx: &mut DocContext<'_>) -> Attributes {
|
||||||
Attributes::from_ast(cx.sess().diagnostic(), self, None)
|
Attributes::from_ast(self, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -850,7 +849,6 @@ where
|
||||||
inputs: (self.0.inputs, self.1).clean(cx),
|
inputs: (self.0.inputs, self.1).clean(cx),
|
||||||
output: self.0.output.clean(cx),
|
output: self.0.output.clean(cx),
|
||||||
c_variadic: self.0.c_variadic,
|
c_variadic: self.0.c_variadic,
|
||||||
attrs: Attributes::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -862,7 +860,6 @@ impl<'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
|
||||||
|
|
||||||
FnDecl {
|
FnDecl {
|
||||||
output: Return(sig.skip_binder().output().clean(cx)),
|
output: Return(sig.skip_binder().output().clean(cx)),
|
||||||
attrs: Attributes::default(),
|
|
||||||
c_variadic: sig.skip_binder().c_variadic,
|
c_variadic: sig.skip_binder().c_variadic,
|
||||||
inputs: Arguments {
|
inputs: Arguments {
|
||||||
values: sig
|
values: sig
|
||||||
|
@ -2001,6 +1998,7 @@ fn clean_extern_crate(
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason
|
// FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason
|
||||||
vec![Item {
|
vec![Item {
|
||||||
name: Some(name),
|
name: Some(name),
|
||||||
|
@ -2008,6 +2006,7 @@ fn clean_extern_crate(
|
||||||
def_id: crate_def_id,
|
def_id: crate_def_id,
|
||||||
visibility: krate.vis.clean(cx),
|
visibility: krate.vis.clean(cx),
|
||||||
kind: box ExternCrateItem { src: orig_name },
|
kind: box ExternCrateItem { src: orig_name },
|
||||||
|
cfg: attrs.cfg(cx.sess().diagnostic()),
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,6 @@ crate struct TraitWithExtraInfo {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
crate struct ExternalCrate {
|
crate struct ExternalCrate {
|
||||||
crate crate_num: CrateNum,
|
crate crate_num: CrateNum,
|
||||||
crate attrs: Attributes,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExternalCrate {
|
impl ExternalCrate {
|
||||||
|
@ -220,11 +219,13 @@ crate struct Item {
|
||||||
/// E.g., struct vs enum vs function.
|
/// E.g., struct vs enum vs function.
|
||||||
crate kind: Box<ItemKind>,
|
crate kind: Box<ItemKind>,
|
||||||
crate def_id: DefId,
|
crate def_id: DefId,
|
||||||
|
|
||||||
|
crate cfg: Option<Arc<Cfg>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
|
// `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||||
rustc_data_structures::static_assert_size!(Item, 40);
|
rustc_data_structures::static_assert_size!(Item, 48);
|
||||||
|
|
||||||
impl fmt::Debug for Item {
|
impl fmt::Debug for Item {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
@ -236,6 +237,7 @@ impl fmt::Debug for Item {
|
||||||
.field("kind", &self.kind)
|
.field("kind", &self.kind)
|
||||||
.field("visibility", &self.visibility)
|
.field("visibility", &self.visibility)
|
||||||
.field("def_id", def_id)
|
.field("def_id", def_id)
|
||||||
|
.field("cfg", &self.cfg)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,6 +265,10 @@ impl Item {
|
||||||
if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id) }
|
if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crate fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
|
||||||
|
if self.is_fake() { false } else { tcx.get_attrs(self.def_id).inner_docs() }
|
||||||
|
}
|
||||||
|
|
||||||
crate fn span(&self, tcx: TyCtxt<'_>) -> Span {
|
crate fn span(&self, tcx: TyCtxt<'_>) -> Span {
|
||||||
let kind = match &*self.kind {
|
let kind = match &*self.kind {
|
||||||
ItemKind::StrippedItem(k) => k,
|
ItemKind::StrippedItem(k) => k,
|
||||||
|
@ -306,12 +312,15 @@ impl Item {
|
||||||
kind: ItemKind,
|
kind: ItemKind,
|
||||||
cx: &mut DocContext<'_>,
|
cx: &mut DocContext<'_>,
|
||||||
) -> Item {
|
) -> Item {
|
||||||
|
let ast_attrs = cx.tcx.get_attrs(def_id);
|
||||||
|
|
||||||
Self::from_def_id_and_attrs_and_parts(
|
Self::from_def_id_and_attrs_and_parts(
|
||||||
def_id,
|
def_id,
|
||||||
name,
|
name,
|
||||||
kind,
|
kind,
|
||||||
box cx.tcx.get_attrs(def_id).clean(cx),
|
box ast_attrs.clean(cx),
|
||||||
cx,
|
cx,
|
||||||
|
ast_attrs.cfg(cx.sess().diagnostic()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,6 +330,7 @@ impl Item {
|
||||||
kind: ItemKind,
|
kind: ItemKind,
|
||||||
attrs: Box<Attributes>,
|
attrs: Box<Attributes>,
|
||||||
cx: &mut DocContext<'_>,
|
cx: &mut DocContext<'_>,
|
||||||
|
cfg: Option<Arc<Cfg>>,
|
||||||
) -> Item {
|
) -> Item {
|
||||||
debug!("name={:?}, def_id={:?}", name, def_id);
|
debug!("name={:?}, def_id={:?}", name, def_id);
|
||||||
|
|
||||||
|
@ -330,6 +340,7 @@ impl Item {
|
||||||
name,
|
name,
|
||||||
attrs,
|
attrs,
|
||||||
visibility: cx.tcx.visibility(def_id).clean(cx),
|
visibility: cx.tcx.visibility(def_id).clean(cx),
|
||||||
|
cfg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,12 +674,72 @@ impl<'a> Iterator for ListAttributesIter<'a> {
|
||||||
crate trait AttributesExt {
|
crate trait AttributesExt {
|
||||||
/// Finds an attribute as List and returns the list of attributes nested inside.
|
/// Finds an attribute as List and returns the list of attributes nested inside.
|
||||||
fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
|
fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
|
||||||
|
|
||||||
|
fn span(&self) -> Option<rustc_span::Span>;
|
||||||
|
|
||||||
|
fn inner_docs(&self) -> bool;
|
||||||
|
|
||||||
|
fn other_attrs(&self) -> Vec<ast::Attribute>;
|
||||||
|
|
||||||
|
fn cfg(&self, diagnostic: &::rustc_errors::Handler) -> Option<Arc<Cfg>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AttributesExt for [ast::Attribute] {
|
impl AttributesExt for [ast::Attribute] {
|
||||||
fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
|
fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
|
||||||
ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name }
|
ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), name }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the span of the first doc-comment, if it exists.
|
||||||
|
fn span(&self) -> Option<rustc_span::Span> {
|
||||||
|
self.iter().find(|attr| attr.doc_str().is_some()).map(|attr| attr.span)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether the first doc-comment is an inner attribute.
|
||||||
|
///
|
||||||
|
//// If there are no doc-comments, return true.
|
||||||
|
/// FIXME(#78591): Support both inner and outer attributes on the same item.
|
||||||
|
fn inner_docs(&self) -> bool {
|
||||||
|
self.iter().find(|a| a.doc_str().is_some()).map_or(true, |a| a.style == AttrStyle::Inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn other_attrs(&self) -> Vec<ast::Attribute> {
|
||||||
|
self.iter().filter(|attr| attr.doc_str().is_none()).cloned().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cfg(&self, diagnostic: &::rustc_errors::Handler) -> Option<Arc<Cfg>> {
|
||||||
|
let mut cfg = Cfg::True;
|
||||||
|
|
||||||
|
for attr in self.iter() {
|
||||||
|
if attr.doc_str().is_none() && attr.has_name(sym::doc) {
|
||||||
|
if let Some(mi) = attr.meta() {
|
||||||
|
if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
|
||||||
|
// Extracted #[doc(cfg(...))]
|
||||||
|
match Cfg::parse(cfg_mi) {
|
||||||
|
Ok(new_cfg) => cfg &= new_cfg,
|
||||||
|
Err(e) => diagnostic.span_err(e.span, e.msg),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for attr in self.lists(sym::target_feature) {
|
||||||
|
if attr.has_name(sym::enable) {
|
||||||
|
if let Some(feat) = attr.value_str() {
|
||||||
|
let meta = attr::mk_name_value_item_str(
|
||||||
|
Ident::with_dummy_span(sym::target_feature),
|
||||||
|
feat,
|
||||||
|
DUMMY_SP,
|
||||||
|
);
|
||||||
|
if let Ok(feat_cfg) = Cfg::parse(&meta) {
|
||||||
|
cfg &= feat_cfg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate trait NestedAttributesExt {
|
crate trait NestedAttributesExt {
|
||||||
|
@ -777,9 +848,6 @@ impl<'a> FromIterator<&'a DocFragment> for String {
|
||||||
crate struct Attributes {
|
crate struct Attributes {
|
||||||
crate doc_strings: Vec<DocFragment>,
|
crate doc_strings: Vec<DocFragment>,
|
||||||
crate other_attrs: Vec<ast::Attribute>,
|
crate other_attrs: Vec<ast::Attribute>,
|
||||||
crate cfg: Option<Arc<Cfg>>,
|
|
||||||
crate span: Option<rustc_span::Span>,
|
|
||||||
crate inner_docs: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||||
|
@ -811,6 +879,10 @@ pub struct RenderedLink {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Attributes {
|
impl Attributes {
|
||||||
|
crate fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
|
||||||
|
self.other_attrs.lists(name)
|
||||||
|
}
|
||||||
|
|
||||||
/// Extracts the content from an attribute `#[doc(cfg(content))]`.
|
/// Extracts the content from an attribute `#[doc(cfg(content))]`.
|
||||||
crate fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
|
crate fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> {
|
||||||
use rustc_ast::NestedMetaItem::MetaItem;
|
use rustc_ast::NestedMetaItem::MetaItem;
|
||||||
|
@ -890,13 +962,10 @@ impl Attributes {
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn from_ast(
|
crate fn from_ast(
|
||||||
diagnostic: &::rustc_errors::Handler,
|
|
||||||
attrs: &[ast::Attribute],
|
attrs: &[ast::Attribute],
|
||||||
additional_attrs: Option<(&[ast::Attribute], DefId)>,
|
additional_attrs: Option<(&[ast::Attribute], DefId)>,
|
||||||
) -> Attributes {
|
) -> Attributes {
|
||||||
let mut doc_strings: Vec<DocFragment> = vec![];
|
let mut doc_strings: Vec<DocFragment> = vec![];
|
||||||
let mut sp = None;
|
|
||||||
let mut cfg = Cfg::True;
|
|
||||||
let mut doc_line = 0;
|
let mut doc_line = 0;
|
||||||
|
|
||||||
fn update_need_backline(doc_strings: &mut Vec<DocFragment>, frag: &DocFragment) {
|
fn update_need_backline(doc_strings: &mut Vec<DocFragment>, frag: &DocFragment) {
|
||||||
|
@ -940,21 +1009,11 @@ impl Attributes {
|
||||||
|
|
||||||
doc_strings.push(frag);
|
doc_strings.push(frag);
|
||||||
|
|
||||||
if sp.is_none() {
|
|
||||||
sp = Some(attr.span);
|
|
||||||
}
|
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
if attr.has_name(sym::doc) {
|
if attr.has_name(sym::doc) {
|
||||||
if let Some(mi) = attr.meta() {
|
if let Some(mi) = attr.meta() {
|
||||||
if let Some(cfg_mi) = Attributes::extract_cfg(&mi) {
|
if let Some((filename, contents)) = Attributes::extract_include(&mi) {
|
||||||
// Extracted #[doc(cfg(...))]
|
|
||||||
match Cfg::parse(cfg_mi) {
|
|
||||||
Ok(new_cfg) => cfg &= new_cfg,
|
|
||||||
Err(e) => diagnostic.span_err(e.span, e.msg),
|
|
||||||
}
|
|
||||||
} else if let Some((filename, contents)) = Attributes::extract_include(&mi)
|
|
||||||
{
|
|
||||||
let line = doc_line;
|
let line = doc_line;
|
||||||
doc_line += contents.as_str().lines().count();
|
doc_line += contents.as_str().lines().count();
|
||||||
let frag = DocFragment {
|
let frag = DocFragment {
|
||||||
|
@ -984,35 +1043,7 @@ impl Attributes {
|
||||||
.filter_map(clean_attr)
|
.filter_map(clean_attr)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// treat #[target_feature(enable = "feat")] attributes as if they were
|
Attributes { doc_strings, other_attrs }
|
||||||
// #[doc(cfg(target_feature = "feat"))] attributes as well
|
|
||||||
for attr in attrs.lists(sym::target_feature) {
|
|
||||||
if attr.has_name(sym::enable) {
|
|
||||||
if let Some(feat) = attr.value_str() {
|
|
||||||
let meta = attr::mk_name_value_item_str(
|
|
||||||
Ident::with_dummy_span(sym::target_feature),
|
|
||||||
feat,
|
|
||||||
DUMMY_SP,
|
|
||||||
);
|
|
||||||
if let Ok(feat_cfg) = Cfg::parse(&meta) {
|
|
||||||
cfg &= feat_cfg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let inner_docs = attrs
|
|
||||||
.iter()
|
|
||||||
.find(|a| a.doc_str().is_some())
|
|
||||||
.map_or(true, |a| a.style == AttrStyle::Inner);
|
|
||||||
|
|
||||||
Attributes {
|
|
||||||
doc_strings,
|
|
||||||
other_attrs,
|
|
||||||
cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
|
|
||||||
span: sp,
|
|
||||||
inner_docs,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds the `doc` attribute as a NameValue and returns the corresponding
|
/// Finds the `doc` attribute as a NameValue and returns the corresponding
|
||||||
|
@ -1078,8 +1109,6 @@ impl Attributes {
|
||||||
impl PartialEq for Attributes {
|
impl PartialEq for Attributes {
|
||||||
fn eq(&self, rhs: &Self) -> bool {
|
fn eq(&self, rhs: &Self) -> bool {
|
||||||
self.doc_strings == rhs.doc_strings
|
self.doc_strings == rhs.doc_strings
|
||||||
&& self.cfg == rhs.cfg
|
|
||||||
&& self.span == rhs.span
|
|
||||||
&& self
|
&& self
|
||||||
.other_attrs
|
.other_attrs
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -1093,20 +1122,12 @@ impl Eq for Attributes {}
|
||||||
impl Hash for Attributes {
|
impl Hash for Attributes {
|
||||||
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
||||||
self.doc_strings.hash(hasher);
|
self.doc_strings.hash(hasher);
|
||||||
self.cfg.hash(hasher);
|
|
||||||
self.span.hash(hasher);
|
|
||||||
for attr in &self.other_attrs {
|
for attr in &self.other_attrs {
|
||||||
attr.id.hash(hasher);
|
attr.id.hash(hasher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AttributesExt for Attributes {
|
|
||||||
fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
|
|
||||||
self.other_attrs.lists(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
crate enum GenericBound {
|
crate enum GenericBound {
|
||||||
TraitBound(PolyTrait, hir::TraitBoundModifier),
|
TraitBound(PolyTrait, hir::TraitBoundModifier),
|
||||||
|
@ -1269,7 +1290,6 @@ crate struct FnDecl {
|
||||||
crate inputs: Arguments,
|
crate inputs: Arguments,
|
||||||
crate output: FnRetTy,
|
crate output: FnRetTy,
|
||||||
crate c_variadic: bool,
|
crate c_variadic: bool,
|
||||||
crate attrs: Attributes,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FnDecl {
|
impl FnDecl {
|
||||||
|
|
|
@ -32,7 +32,7 @@ use std::rc::Rc;
|
||||||
|
|
||||||
use crate::clean;
|
use crate::clean;
|
||||||
use crate::clean::inline::build_external_trait;
|
use crate::clean::inline::build_external_trait;
|
||||||
use crate::clean::{AttributesExt, TraitWithExtraInfo, MAX_DEF_IDX};
|
use crate::clean::{TraitWithExtraInfo, MAX_DEF_IDX};
|
||||||
use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions};
|
use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions};
|
||||||
use crate::formats::cache::Cache;
|
use crate::formats::cache::Cache;
|
||||||
use crate::passes::{self, Condition::*, ConditionalPass};
|
use crate::passes::{self, Condition::*, ConditionalPass};
|
||||||
|
|
|
@ -26,7 +26,7 @@ use std::str;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use crate::clean::Attributes;
|
use crate::clean::{types::AttributesExt, Attributes};
|
||||||
use crate::config::Options;
|
use crate::config::Options;
|
||||||
use crate::html::markdown::{self, ErrorCodes, Ignore, LangString};
|
use crate::html::markdown::{self, ErrorCodes, Ignore, LangString};
|
||||||
use crate::lint::init_lints;
|
use crate::lint::init_lints;
|
||||||
|
@ -1092,9 +1092,10 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
|
||||||
sp: Span,
|
sp: Span,
|
||||||
nested: F,
|
nested: F,
|
||||||
) {
|
) {
|
||||||
let attrs = self.tcx.hir().attrs(hir_id);
|
let ast_attrs = self.tcx.hir().attrs(hir_id);
|
||||||
let mut attrs = Attributes::from_ast(self.sess.diagnostic(), attrs, None);
|
let mut attrs = Attributes::from_ast(ast_attrs, None);
|
||||||
if let Some(ref cfg) = attrs.cfg {
|
|
||||||
|
if let Some(ref cfg) = ast_attrs.cfg(self.sess.diagnostic()) {
|
||||||
if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features_untracked())) {
|
if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features_untracked())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1110,8 +1111,8 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
|
||||||
// anything else, this will combine them for us.
|
// anything else, this will combine them for us.
|
||||||
if let Some(doc) = attrs.collapsed_doc_value() {
|
if let Some(doc) = attrs.collapsed_doc_value() {
|
||||||
// Use the outermost invocation, so that doctest names come from where the docs were written.
|
// Use the outermost invocation, so that doctest names come from where the docs were written.
|
||||||
let span = attrs
|
let span = ast_attrs
|
||||||
.span
|
.span()
|
||||||
.map(|span| span.ctxt().outer_expn().expansion_cause().unwrap_or(span))
|
.map(|span| span.ctxt().outer_expn().expansion_cause().unwrap_or(span))
|
||||||
.unwrap_or(DUMMY_SP);
|
.unwrap_or(DUMMY_SP);
|
||||||
self.collector.set_position(span);
|
self.collector.set_position(span);
|
||||||
|
|
|
@ -164,10 +164,12 @@ impl Cache {
|
||||||
};
|
};
|
||||||
let name = e.name(tcx);
|
let name = e.name(tcx);
|
||||||
let extern_url = extern_html_root_urls.get(&*name.as_str()).map(|u| &**u);
|
let extern_url = extern_html_root_urls.get(&*name.as_str()).map(|u| &**u);
|
||||||
self.extern_locations
|
|
||||||
.insert(n, (name, src_root, extern_location(e, extern_url, &dst, tcx)));
|
|
||||||
|
|
||||||
let did = DefId { krate: n, index: CRATE_DEF_INDEX };
|
let did = DefId { krate: n, index: CRATE_DEF_INDEX };
|
||||||
|
self.extern_locations.insert(
|
||||||
|
n,
|
||||||
|
(name, src_root, extern_location(e, extern_url, tcx.get_attrs(did), &dst, tcx)),
|
||||||
|
);
|
||||||
|
|
||||||
self.external_paths.insert(did, (vec![name.to_string()], ItemType::Module));
|
self.external_paths.insert(did, (vec![name.to_string()], ItemType::Module));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use rustc_ast::ast;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
use serde::ser::{Serialize, SerializeStruct, Serializer};
|
use serde::ser::{Serialize, SerializeStruct, Serializer};
|
||||||
|
|
||||||
|
use crate::clean;
|
||||||
use crate::clean::types::{
|
use crate::clean::types::{
|
||||||
FnDecl, FnRetTy, GenericBound, Generics, GetDefId, Type, WherePredicate,
|
AttributesExt, FnDecl, FnRetTy, GenericBound, Generics, GetDefId, Type, WherePredicate,
|
||||||
};
|
};
|
||||||
use crate::clean::{self, AttributesExt};
|
|
||||||
use crate::formats::cache::Cache;
|
use crate::formats::cache::Cache;
|
||||||
use crate::formats::item_type::ItemType;
|
use crate::formats::item_type::ItemType;
|
||||||
use crate::html::markdown::short_markdown_summary;
|
use crate::html::markdown::short_markdown_summary;
|
||||||
|
@ -30,6 +31,7 @@ crate enum ExternalLocation {
|
||||||
crate fn extern_location(
|
crate fn extern_location(
|
||||||
e: &clean::ExternalCrate,
|
e: &clean::ExternalCrate,
|
||||||
extern_url: Option<&str>,
|
extern_url: Option<&str>,
|
||||||
|
ast_attrs: &[ast::Attribute],
|
||||||
dst: &Path,
|
dst: &Path,
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
) -> ExternalLocation {
|
) -> ExternalLocation {
|
||||||
|
@ -50,7 +52,7 @@ crate fn extern_location(
|
||||||
|
|
||||||
// Failing that, see if there's an attribute specifying where to find this
|
// Failing that, see if there's an attribute specifying where to find this
|
||||||
// external crate
|
// external crate
|
||||||
e.attrs
|
ast_attrs
|
||||||
.lists(sym::doc)
|
.lists(sym::doc)
|
||||||
.filter(|a| a.has_name(sym::html_root_url))
|
.filter(|a| a.has_name(sym::html_root_url))
|
||||||
.filter_map(|a| a.value_str())
|
.filter_map(|a| a.value_str())
|
||||||
|
|
|
@ -18,7 +18,7 @@ use super::print_item::{full_path, item_path, print_item};
|
||||||
use super::write_shared::write_shared;
|
use super::write_shared::write_shared;
|
||||||
use super::{print_sidebar, settings, AllTypes, NameDoc, StylePath, BASIC_KEYWORDS};
|
use super::{print_sidebar, settings, AllTypes, NameDoc, StylePath, BASIC_KEYWORDS};
|
||||||
|
|
||||||
use crate::clean::{self, AttributesExt};
|
use crate::clean;
|
||||||
use crate::config::RenderOptions;
|
use crate::config::RenderOptions;
|
||||||
use crate::docfs::{DocFS, PathError};
|
use crate::docfs::{DocFS, PathError};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
|
|
|
@ -608,17 +608,12 @@ fn document_item_info(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn portability(item: &clean::Item, parent: Option<&clean::Item>) -> Option<String> {
|
fn portability(item: &clean::Item, parent: Option<&clean::Item>) -> Option<String> {
|
||||||
let cfg = match (&item.attrs.cfg, parent.and_then(|p| p.attrs.cfg.as_ref())) {
|
let cfg = match (&item.cfg, parent.and_then(|p| p.cfg.as_ref())) {
|
||||||
(Some(cfg), Some(parent_cfg)) => cfg.simplify_with(parent_cfg),
|
(Some(cfg), Some(parent_cfg)) => cfg.simplify_with(parent_cfg),
|
||||||
(cfg, _) => cfg.as_deref().cloned(),
|
(cfg, _) => cfg.as_deref().cloned(),
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!(
|
debug!("Portability {:?} - {:?} = {:?}", item.cfg, parent.and_then(|p| p.cfg.as_ref()), cfg);
|
||||||
"Portability {:?} - {:?} = {:?}",
|
|
||||||
item.attrs.cfg,
|
|
||||||
parent.and_then(|p| p.attrs.cfg.as_ref()),
|
|
||||||
cfg
|
|
||||||
);
|
|
||||||
|
|
||||||
Some(format!("<div class=\"stab portability\">{}</div>", cfg?.render_long_html()))
|
Some(format!("<div class=\"stab portability\">{}</div>", cfg?.render_long_html()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
use clean::AttributesExt;
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::CtorKind;
|
use rustc_hir::def::CtorKind;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::dep_graph::DepContext;
|
|
||||||
use rustc_middle::middle::stability;
|
use rustc_middle::middle::stability;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_span::hygiene::MacroKind;
|
use rustc_span::hygiene::MacroKind;
|
||||||
|
@ -284,16 +285,14 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
|
||||||
|
|
||||||
clean::ImportItem(ref import) => {
|
clean::ImportItem(ref import) => {
|
||||||
let (stab, stab_tags) = if let Some(import_def_id) = import.source.did {
|
let (stab, stab_tags) = if let Some(import_def_id) = import.source.did {
|
||||||
let import_attrs = Box::new(clean::Attributes::from_ast(
|
let ast_attrs = cx.tcx().get_attrs(import_def_id);
|
||||||
cx.tcx().sess().diagnostic(),
|
let import_attrs = Box::new(clean::Attributes::from_ast(ast_attrs, None));
|
||||||
cx.tcx().get_attrs(import_def_id),
|
|
||||||
None,
|
|
||||||
));
|
|
||||||
|
|
||||||
// Just need an item with the correct def_id and attrs
|
// Just need an item with the correct def_id and attrs
|
||||||
let import_item = clean::Item {
|
let import_item = clean::Item {
|
||||||
def_id: import_def_id,
|
def_id: import_def_id,
|
||||||
attrs: import_attrs,
|
attrs: import_attrs,
|
||||||
|
cfg: ast_attrs.cfg(cx.tcx().sess.diagnostic()),
|
||||||
..myitem.clone()
|
..myitem.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -400,12 +399,12 @@ fn extra_info_tags(item: &clean::Item, parent: &clean::Item, tcx: TyCtxt<'_>) ->
|
||||||
tags += &tag_html("unstable", "", "Experimental");
|
tags += &tag_html("unstable", "", "Experimental");
|
||||||
}
|
}
|
||||||
|
|
||||||
let cfg = match (&item.attrs.cfg, parent.attrs.cfg.as_ref()) {
|
let cfg = match (&item.cfg, parent.cfg.as_ref()) {
|
||||||
(Some(cfg), Some(parent_cfg)) => cfg.simplify_with(parent_cfg),
|
(Some(cfg), Some(parent_cfg)) => cfg.simplify_with(parent_cfg),
|
||||||
(cfg, _) => cfg.as_deref().cloned(),
|
(cfg, _) => cfg.as_deref().cloned(),
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("Portability {:?} - {:?} = {:?}", item.attrs.cfg, parent.attrs.cfg, cfg);
|
debug!("Portability {:?} - {:?} = {:?}", item.cfg, parent.cfg, cfg);
|
||||||
if let Some(ref cfg) = cfg {
|
if let Some(ref cfg) = cfg {
|
||||||
tags += &tag_html("portability", &cfg.render_long_plain(), &cfg.render_short_html());
|
tags += &tag_html("portability", &cfg.render_long_plain(), &cfg.render_short_html());
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ impl JsonRenderer<'_> {
|
||||||
.map(rustc_ast_pretty::pprust::attribute_to_string)
|
.map(rustc_ast_pretty::pprust::attribute_to_string)
|
||||||
.collect();
|
.collect();
|
||||||
let span = item.span(self.tcx);
|
let span = item.span(self.tcx);
|
||||||
let clean::Item { name, attrs: _, kind: _, visibility, def_id } = item;
|
let clean::Item { name, attrs: _, kind: _, visibility, def_id, cfg: _ } = item;
|
||||||
let inner = match *item.kind {
|
let inner = match *item.kind {
|
||||||
clean::StrippedItem(_) => return None,
|
clean::StrippedItem(_) => return None,
|
||||||
_ => from_clean_item(item, self.tcx),
|
_ => from_clean_item(item, self.tcx),
|
||||||
|
@ -421,7 +421,7 @@ impl FromWithTcx<clean::BareFunctionDecl> for FunctionPointer {
|
||||||
|
|
||||||
impl FromWithTcx<clean::FnDecl> for FnDecl {
|
impl FromWithTcx<clean::FnDecl> for FnDecl {
|
||||||
fn from_tcx(decl: clean::FnDecl, tcx: TyCtxt<'_>) -> Self {
|
fn from_tcx(decl: clean::FnDecl, tcx: TyCtxt<'_>) -> Self {
|
||||||
let clean::FnDecl { inputs, output, c_variadic, attrs: _ } = decl;
|
let clean::FnDecl { inputs, output, c_variadic } = decl;
|
||||||
FnDecl {
|
FnDecl {
|
||||||
inputs: inputs
|
inputs: inputs
|
||||||
.values
|
.values
|
||||||
|
|
|
@ -853,7 +853,9 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if item.is_mod() && item.attrs.inner_docs {
|
let inner_docs = item.inner_docs(self.cx.tcx);
|
||||||
|
|
||||||
|
if item.is_mod() && inner_docs {
|
||||||
self.mod_ids.push(item.def_id);
|
self.mod_ids.push(item.def_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -880,7 +882,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(if item.is_mod() {
|
Some(if item.is_mod() {
|
||||||
if !item.attrs.inner_docs {
|
if !inner_docs {
|
||||||
self.mod_ids.push(item.def_id);
|
self.mod_ids.push(item.def_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1050,6 +1052,8 @@ impl LinkCollector<'_, '_> {
|
||||||
};
|
};
|
||||||
let mut path_str = &*path_str;
|
let mut path_str = &*path_str;
|
||||||
|
|
||||||
|
let inner_docs = item.inner_docs(self.cx.tcx);
|
||||||
|
|
||||||
// In order to correctly resolve intra-doc links we need to
|
// In order to correctly resolve intra-doc links we need to
|
||||||
// pick a base AST node to work from. If the documentation for
|
// pick a base AST node to work from. If the documentation for
|
||||||
// this module came from an inner comment (//!) then we anchor
|
// this module came from an inner comment (//!) then we anchor
|
||||||
|
@ -1061,11 +1065,8 @@ impl LinkCollector<'_, '_> {
|
||||||
// we've already pushed this node onto the resolution stack but
|
// we've already pushed this node onto the resolution stack but
|
||||||
// for outer comments we explicitly try and resolve against the
|
// for outer comments we explicitly try and resolve against the
|
||||||
// parent_node first.
|
// parent_node first.
|
||||||
let base_node = if item.is_mod() && item.attrs.inner_docs {
|
let base_node =
|
||||||
self.mod_ids.last().copied()
|
if item.is_mod() && inner_docs { self.mod_ids.last().copied() } else { parent_node };
|
||||||
} else {
|
|
||||||
parent_node
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut module_id = if let Some(id) = base_node {
|
let mut module_id = if let Some(id) = base_node {
|
||||||
id
|
id
|
||||||
|
|
|
@ -24,7 +24,7 @@ impl DocFolder for CfgPropagator {
|
||||||
fn fold_item(&mut self, mut item: Item) -> Option<Item> {
|
fn fold_item(&mut self, mut item: Item) -> Option<Item> {
|
||||||
let old_parent_cfg = self.parent_cfg.clone();
|
let old_parent_cfg = self.parent_cfg.clone();
|
||||||
|
|
||||||
let new_cfg = match (self.parent_cfg.take(), item.attrs.cfg.take()) {
|
let new_cfg = match (self.parent_cfg.take(), item.cfg.take()) {
|
||||||
(None, None) => None,
|
(None, None) => None,
|
||||||
(Some(rc), None) | (None, Some(rc)) => Some(rc),
|
(Some(rc), None) | (None, Some(rc)) => Some(rc),
|
||||||
(Some(mut a), Some(b)) => {
|
(Some(mut a), Some(b)) => {
|
||||||
|
@ -34,7 +34,7 @@ impl DocFolder for CfgPropagator {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.parent_cfg = new_cfg.clone();
|
self.parent_cfg = new_cfg.clone();
|
||||||
item.attrs.cfg = new_cfg;
|
item.cfg = new_cfg;
|
||||||
|
|
||||||
let result = self.fold_item_recur(item);
|
let result = self.fold_item_recur(item);
|
||||||
self.parent_cfg = old_parent_cfg;
|
self.parent_cfg = old_parent_cfg;
|
||||||
|
|
|
@ -2,8 +2,8 @@ use rustc_hir::def_id::DefIdSet;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use crate::clean::Item;
|
use crate::clean;
|
||||||
use crate::clean::{self, AttributesExt, NestedAttributesExt};
|
use crate::clean::{Item, NestedAttributesExt};
|
||||||
use crate::core::DocContext;
|
use crate::core::DocContext;
|
||||||
use crate::fold::{DocFolder, StripItem};
|
use crate::fold::{DocFolder, StripItem};
|
||||||
use crate::passes::{ImplStripper, Pass};
|
use crate::passes::{ImplStripper, Pass};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue