use deref_patterns in rustdoc

This commit is contained in:
cyrgani
2026-05-13 10:55:37 +00:00
parent c8c4c83d57
commit 6e99c68516
16 changed files with 111 additions and 106 deletions
+4 -4
View File
@@ -149,7 +149,7 @@ fn should_append_only_to_description(&self) -> bool {
| CfgEntry::All(..)
| CfgEntry::NameValue { .. }
| CfgEntry::Version(..)
| CfgEntry::Not(box CfgEntry::NameValue { .. }, _) => true,
| CfgEntry::Not(CfgEntry::NameValue { .. }, _) => true,
CfgEntry::Not(..) | CfgEntry::Bool(..) => false,
}
}
@@ -386,7 +386,7 @@ fn display_sub_cfgs(
impl fmt::Display for Display<'_> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.0 {
CfgEntry::Not(box CfgEntry::Any(sub_cfgs, _), _) => {
CfgEntry::Not(CfgEntry::Any(sub_cfgs, _), _) => {
let separator = if sub_cfgs.iter().all(is_simple_cfg) { " nor " } else { ", nor " };
fmt.write_str("neither ")?;
@@ -399,10 +399,10 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
})
.joined(separator, fmt)
}
CfgEntry::Not(box simple @ CfgEntry::NameValue { .. }, _) => {
CfgEntry::Not(simple @ CfgEntry::NameValue { .. }, _) => {
write!(fmt, "non-{}", Display(simple, self.1))
}
CfgEntry::Not(box c, _) => write!(fmt, "not ({})", Display(c, self.1)),
CfgEntry::Not(c, _) => write!(fmt, "not ({})", Display(c, self.1)),
CfgEntry::Any(sub_cfgs, _) => {
let separator = if sub_cfgs.iter().all(is_simple_cfg) { " or " } else { ", or " };
+3 -6
View File
@@ -1472,11 +1472,8 @@ fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
generics.where_predicates.retain_mut(|pred| match *pred {
WherePredicate::BoundPredicate {
ty:
QPath(box QPathData {
ref assoc,
ref self_type,
trait_: Some(ref trait_),
..
QPath(QPathData {
ref assoc, ref self_type, trait_: Some(ref trait_), ..
}),
bounds: ref mut pred_bounds,
..
@@ -2786,7 +2783,7 @@ fn add_without_unwanted_attributes<'hir>(
hir::Attribute::Parsed(AttributeKind::DocComment { .. }) => {
attrs.push((Cow::Borrowed(attr), import_parent));
}
hir::Attribute::Parsed(AttributeKind::Doc(box d)) => {
hir::Attribute::Parsed(AttributeKind::Doc(d)) => {
// Remove attributes from `normal` that should not be inherited by `use` re-export.
let DocAttribute {
first_span: _,
+17 -12
View File
@@ -491,7 +491,7 @@ pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
/// Returns true if item is an associated function with a `self` parameter.
pub(crate) fn has_self_param(&self) -> bool {
if let ItemKind::MethodItem(box Function { decl, .. }, _) = &self.inner.kind {
if let ItemKind::MethodItem(Function { decl, .. }, _) = &self.inner.kind {
decl.receiver_type().is_some()
} else {
false
@@ -505,8 +505,8 @@ pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option<Span> {
};
match kind {
ItemKind::ModuleItem(Module { span, .. }) => Some(*span),
ItemKind::ImplItem(box Impl { kind: ImplKind::Auto, .. }) => None,
ItemKind::ImplItem(box Impl { kind: ImplKind::Blanket(_), .. }) => {
ItemKind::ImplItem(Impl { kind: ImplKind::Auto, .. }) => None,
ItemKind::ImplItem(Impl { kind: ImplKind::Blanket(_), .. }) => {
if let ItemId::Blanket { impl_id, .. } = self.item_id {
Some(rustc_span(impl_id, tcx))
} else {
@@ -667,16 +667,21 @@ pub(crate) fn is_variant(&self) -> bool {
self.type_() == ItemType::Variant
}
pub(crate) fn is_associated_type(&self) -> bool {
matches!(self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..)))
matches!(self.kind, AssocTypeItem(..) | StrippedItem(AssocTypeItem(..)))
}
pub(crate) fn is_required_associated_type(&self) -> bool {
matches!(self.kind, RequiredAssocTypeItem(..) | StrippedItem(box RequiredAssocTypeItem(..)))
matches!(self.kind, RequiredAssocTypeItem(..) | StrippedItem(RequiredAssocTypeItem(..)))
}
pub(crate) fn is_associated_const(&self) -> bool {
matches!(self.kind, ProvidedAssocConstItem(..) | ImplAssocConstItem(..) | StrippedItem(box (ProvidedAssocConstItem(..) | ImplAssocConstItem(..))))
matches!(
self.kind,
ProvidedAssocConstItem(..)
| ImplAssocConstItem(..)
| StrippedItem(ProvidedAssocConstItem(..) | ImplAssocConstItem(..))
)
}
pub(crate) fn is_required_associated_const(&self) -> bool {
matches!(self.kind, RequiredAssocConstItem(..) | StrippedItem(box RequiredAssocConstItem(..)))
matches!(self.kind, RequiredAssocConstItem(..) | StrippedItem(RequiredAssocConstItem(..)))
}
pub(crate) fn is_method(&self) -> bool {
self.type_() == ItemType::Method
@@ -1508,9 +1513,9 @@ pub(crate) fn is_doc_subtype_of(&self, other: &Self, cache: &Cache) -> bool {
pub(crate) fn primitive_type(&self) -> Option<PrimitiveType> {
match *self {
Primitive(p) | BorrowedRef { type_: box Primitive(p), .. } => Some(p),
Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
Primitive(p) | BorrowedRef { type_: Primitive(p), .. } => Some(p),
Slice(..) | BorrowedRef { type_: Slice(..), .. } => Some(PrimitiveType::Slice),
Array(..) | BorrowedRef { type_: Array(..), .. } => Some(PrimitiveType::Array),
Tuple(ref tys) => {
if tys.is_empty() {
Some(PrimitiveType::Unit)
@@ -1590,7 +1595,7 @@ pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
Type::Path { path } => return Some(path.def_id()),
DynTrait(bounds, _) => return bounds.first().map(|b| b.trait_.def_id()),
Primitive(p) => return cache.primitive_locations.get(p).cloned(),
BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
BorrowedRef { type_: Generic(..), .. } => PrimitiveType::Reference,
BorrowedRef { type_, .. } => return type_.def_id(cache),
Tuple(tys) => {
if tys.is_empty() {
@@ -1605,7 +1610,7 @@ pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
Type::Pat(..) => PrimitiveType::Pat,
Type::FieldOf(..) => PrimitiveType::FieldOf,
RawPointer(..) => PrimitiveType::RawPointer,
QPath(box QPathData { self_type, .. }) => return self_type.def_id(cache),
QPath(QPathData { self_type, .. }) => return self_type.def_id(cache),
Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
};
Primitive(t).def_id(cache)
+1 -1
View File
@@ -105,7 +105,7 @@ fn fold_inner_recur(&mut self, kind: ItemKind) -> ItemKind {
/// don't override!
fn fold_item_recur(&mut self, mut item: Item) -> Item {
item.inner.kind = match item.inner.kind {
StrippedItem(box i) => StrippedItem(Box::new(self.fold_inner_recur(i))),
StrippedItem(i) => StrippedItem(Box::new(self.fold_inner_recur(*i))),
_ => self.fold_inner_recur(item.inner.kind),
};
item
+59 -59
View File
@@ -248,7 +248,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
// If this is a stripped module,
// we don't want it or its children in the search index.
let orig_stripped_mod = match item.kind {
clean::StrippedItem(box clean::ModuleItem(..)) => {
clean::StrippedItem(clean::ModuleItem(..)) => {
mem::replace(&mut self.cache.stripped_mod, true)
}
_ => self.cache.stripped_mod,
@@ -409,69 +409,69 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
// Once we've recursively found all the generics, hoard off all the
// implementations elsewhere.
let ret = if let clean::Item {
inner: box clean::ItemInner { kind: clean::ImplItem(ref i), .. },
} = item
{
// Figure out the id of this impl. This may map to a
// primitive rather than always to a struct/enum.
// Note: matching twice to restrict the lifetime of the `i` borrow.
let mut dids = FxIndexSet::default();
match i.for_ {
clean::Type::Path { ref path }
| clean::BorrowedRef { type_: box clean::Type::Path { ref path }, .. } => {
dids.insert(path.def_id());
if let Some(generics) = path.generics()
&& let ty::Adt(adt, _) = self
.tcx
.type_of(path.def_id())
.instantiate_identity()
.skip_norm_wip()
.kind()
&& adt.is_fundamental()
{
for ty in generics {
dids.extend(ty.def_id(self.cache));
let ret =
if let clean::Item { inner: clean::ItemInner { kind: clean::ImplItem(ref i), .. } } =
item
{
// Figure out the id of this impl. This may map to a
// primitive rather than always to a struct/enum.
// Note: matching twice to restrict the lifetime of the `i` borrow.
let mut dids = FxIndexSet::default();
match i.for_ {
clean::Type::Path { ref path }
| clean::BorrowedRef { type_: clean::Type::Path { ref path }, .. } => {
dids.insert(path.def_id());
if let Some(generics) = path.generics()
&& let ty::Adt(adt, _) = self
.tcx
.type_of(path.def_id())
.instantiate_identity()
.skip_norm_wip()
.kind()
&& adt.is_fundamental()
{
for ty in generics {
dids.extend(ty.def_id(self.cache));
}
}
}
}
clean::DynTrait(ref bounds, _)
| clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => {
dids.insert(bounds[0].trait_.def_id());
}
ref t => {
let did = t
.primitive_type()
.and_then(|t| self.cache.primitive_locations.get(&t).cloned());
clean::DynTrait(ref bounds, _)
| clean::BorrowedRef { type_: clean::DynTrait(ref bounds, _), .. } => {
dids.insert(bounds[0].trait_.def_id());
}
ref t => {
let did = t
.primitive_type()
.and_then(|t| self.cache.primitive_locations.get(&t).cloned());
dids.extend(did);
}
}
if let Some(trait_) = &i.trait_
&& let Some(generics) = trait_.generics()
{
for bound in generics {
dids.extend(bound.def_id(self.cache));
}
}
let impl_item = Impl { impl_item: item };
let impl_did = impl_item.def_id();
let trait_did = impl_item.trait_did();
if trait_did.is_none_or(|d| self.cache.traits.contains_key(&d)) {
for did in dids {
if self.impl_ids.entry(did).or_default().insert(impl_did) {
self.cache.impls.entry(did).or_default().push(impl_item.clone());
dids.extend(did);
}
}
if let Some(trait_) = &i.trait_
&& let Some(generics) = trait_.generics()
{
for bound in generics {
dids.extend(bound.def_id(self.cache));
}
}
let impl_item = Impl { impl_item: item };
let impl_did = impl_item.def_id();
let trait_did = impl_item.trait_did();
if trait_did.is_none_or(|d| self.cache.traits.contains_key(&d)) {
for did in dids {
if self.impl_ids.entry(did).or_default().insert(impl_did) {
self.cache.impls.entry(did).or_default().push(impl_item.clone());
}
}
} else {
let trait_did = trait_did.expect("no trait did");
self.cache.orphan_trait_impls.push((trait_did, dids, impl_item));
}
None
} else {
let trait_did = trait_did.expect("no trait did");
self.cache.orphan_trait_impls.push((trait_did, dids, impl_item));
}
None
} else {
Some(item)
};
Some(item)
};
if pushed {
self.cache.stack.pop().expect("stack already empty");
@@ -655,7 +655,7 @@ enum ParentStackItem {
impl ParentStackItem {
fn new(item: &clean::Item) -> Self {
match &item.kind {
clean::ItemKind::ImplItem(box clean::Impl { for_, trait_, generics, kind, .. }) => {
clean::ItemKind::ImplItem(clean::Impl { for_, trait_, generics, kind, .. }) => {
ParentStackItem::Impl {
for_: for_.clone(),
trait_: trait_.clone(),
+1 -1
View File
@@ -106,7 +106,7 @@ fn visit_u64<E: de::Error>(self, v: u64) -> Result<ItemType, E> {
impl<'a> From<&'a clean::Item> for ItemType {
fn from(item: &'a clean::Item) -> ItemType {
let kind = match &item.kind {
clean::StrippedItem(box item) => item,
clean::StrippedItem(item) => item,
kind => kind,
};
+2 -2
View File
@@ -75,8 +75,8 @@ fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string());
cx.mod_item_in(item)?;
let (clean::StrippedItem(box clean::ModuleItem(ref module))
| clean::ModuleItem(ref module)) = item.inner.kind
let (clean::StrippedItem(clean::ModuleItem(ref module)) | clean::ModuleItem(ref module)) =
item.inner.kind
else {
unreachable!()
};
+3 -3
View File
@@ -961,7 +961,7 @@ fn fmt_type(
}
}
},
clean::Slice(box clean::Generic(name)) => {
clean::Slice(clean::Generic(name)) => {
primitive_link(f, PrimitiveType::Slice, format_args!("[{name}]"), cx)
}
clean::Slice(t) => Wrapped::with_square_brackets().wrap(print_type(t, cx)).fmt(f),
@@ -974,7 +974,7 @@ fn fmt_type(
fmt::Display::fmt(&print_type(t, cx), f)?;
write!(f, ", {field})")
}
clean::Array(box clean::Generic(name), n) if !f.alternate() => primitive_link(
clean::Array(clean::Generic(name), n) if !f.alternate() => primitive_link(
f,
PrimitiveType::Array,
format_args!("[{name}; {n}]", n = Escape(n)),
@@ -1280,7 +1280,7 @@ fn print_parameter(parameter: &clean::Parameter, cx: &Context<'_>) -> impl fmt::
if let Some(self_ty) = parameter.to_receiver() {
match self_ty {
clean::SelfTy => f.write_str("self"),
clean::BorrowedRef { lifetime, mutability, type_: box clean::SelfTy } => {
clean::BorrowedRef { lifetime, mutability, type_: clean::SelfTy } => {
f.write_str(if f.alternate() { "&" } else { "&amp;" })?;
if let Some(lt) = lifetime {
write!(f, "{lt} ", lt = print_lifetime(lt))?;
+1 -1
View File
@@ -832,7 +832,7 @@ fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error> {
// Render sidebar-items.js used throughout this module.
if !self.info.render_redirect_pages {
let (clean::StrippedItem(box clean::ModuleItem(ref module))
let (clean::StrippedItem(clean::ModuleItem(ref module))
| clean::ModuleItem(ref module)) = item.kind
else {
unreachable!()
+4 -3
View File
@@ -809,7 +809,8 @@ fn document_full_inner(
}
let kind = match &item.kind {
clean::ItemKind::StrippedItem(box kind) | kind => kind,
clean::ItemKind::StrippedItem(kind) => kind,
kind => kind,
};
if let clean::ItemKind::FunctionItem(..) | clean::ItemKind::MethodItem(..) = kind {
@@ -1582,7 +1583,7 @@ fn render_deref_methods(
.items
.iter()
.find_map(|item| match item.kind {
clean::AssocTypeItem(box ref t, _) => Some(match *t {
clean::AssocTypeItem(ref t, _) => Some(match *t {
clean::TypeAlias { item_type: Some(ref type_), .. } => (type_, &t.type_),
_ => (&t.type_, &t.type_),
}),
@@ -2709,7 +2710,7 @@ fn collect_paths_for_type(first_ty: &clean::Type, cache: &Cache) -> Vec<String>
clean::Type::BorrowedRef { type_, .. } => {
work.push_back(type_);
}
clean::Type::QPath(box clean::QPathData { self_type, trait_, .. }) => {
clean::Type::QPath(clean::QPathData { self_type, trait_, .. }) => {
work.push_back(self_type);
if let Some(trait_) = trait_ {
process_path(trait_.def_id());
+7 -8
View File
@@ -1524,9 +1524,8 @@ fn item_union(cx: &Context<'_>, it: &clean::Item, s: &clean::Union) -> impl fmt:
fn print_tuple_struct_fields(cx: &Context<'_>, s: &[clean::Item]) -> impl Display {
fmt::from_fn(|f| {
if !s.is_empty()
&& s.iter().all(|field| {
matches!(field.kind, clean::StrippedItem(box clean::StructFieldItem(..)))
})
&& s.iter()
.all(|field| matches!(field.kind, clean::StrippedItem(clean::StructFieldItem(..))))
{
return f.write_str("<span class=\"comment\">/* private fields */</span>");
}
@@ -1534,7 +1533,7 @@ fn print_tuple_struct_fields(cx: &Context<'_>, s: &[clean::Item]) -> impl Displa
s.iter()
.map(|ty| {
fmt::from_fn(|f| match ty.kind {
clean::StrippedItem(box clean::StructFieldItem(_)) => f.write_str("_"),
clean::StrippedItem(clean::StructFieldItem(_)) => f.write_str("_"),
clean::StructFieldItem(ref ty) => write!(f, "{}", print_type(ty, cx)),
_ => unreachable!(),
})
@@ -1852,7 +1851,7 @@ fn item_variants(
)?;
for field in fields {
match field.kind {
clean::StrippedItem(box clean::StructFieldItem(_)) => {}
clean::StrippedItem(clean::StructFieldItem(_)) => {}
clean::StructFieldItem(ref ty) => {
let id = cx.derive_id(format!(
"variant.{}.field.{}",
@@ -2355,7 +2354,7 @@ fn render_implementor(
// full path, for example in `std::iter::ExactSizeIterator`
let use_absolute = match implementor.inner_impl().for_ {
clean::Type::Path { ref path, .. }
| clean::BorrowedRef { type_: box clean::Type::Path { ref path, .. }, .. }
| clean::BorrowedRef { type_: clean::Type::Path { ref path, .. }, .. }
if !path.is_assoc_ty() =>
{
implementor_dups[&path.last()].1
@@ -2551,7 +2550,7 @@ fn render_struct_fields(
w.write_str("(")?;
if !fields.is_empty()
&& fields.iter().all(|field| {
matches!(field.kind, clean::StrippedItem(box clean::StructFieldItem(..)))
matches!(field.kind, clean::StrippedItem(clean::StructFieldItem(..)))
})
{
write!(w, "<span class=\"comment\">/* private fields */</span>")?;
@@ -2561,7 +2560,7 @@ fn render_struct_fields(
w.write_str(", ")?;
}
match field.kind {
clean::StrippedItem(box clean::StructFieldItem(..)) => {
clean::StrippedItem(clean::StructFieldItem(..)) => {
write!(w, "_")?;
}
clean::StructFieldItem(ref ty) => {
+1 -1
View File
@@ -526,7 +526,7 @@ fn sidebar_deref_methods<'a>(
debug!("found Deref: {impl_:?}");
if let Some((target, real_target)) =
impl_.inner_impl().items.iter().find_map(|item| match item.kind {
clean::AssocTypeItem(box ref t, _) => Some(match *t {
clean::AssocTypeItem(ref t, _) => Some(match *t {
clean::TypeAlias { item_type: Some(ref type_), .. } => (type_, &t.type_),
_ => (&t.type_, &t.type_),
}),
+1 -1
View File
@@ -232,7 +232,7 @@ fn from_clean(arg: &clean::GenericArg, renderer: &JsonRenderer<'_>) -> Self {
match arg {
Lifetime(l) => GenericArg::Lifetime(l.into_json(renderer)),
Type(t) => GenericArg::Type(t.into_json(renderer)),
Const(box c) => GenericArg::Const(c.into_json(renderer)),
Const(c) => GenericArg::Const(c.into_json(renderer)),
Infer => GenericArg::Infer,
}
}
+1 -1
View File
@@ -5,7 +5,7 @@
)]
#![feature(ascii_char)]
#![feature(ascii_char_variants)]
#![feature(box_patterns)]
#![feature(deref_patterns)]
#![feature(file_buffered)]
#![feature(formatting_options)]
#![feature(iter_intersperse)]
+2 -2
View File
@@ -155,7 +155,7 @@ fn add_deref_target(
// scan through included items ahead of time to splice in Deref targets to the "valid" sets
for it in new_items_external.iter().chain(new_items_local.iter()) {
if let ImplItem(box Impl { ref for_, ref trait_, ref items, polarity, .. }) = it.kind
if let ImplItem(Impl { ref for_, ref trait_, ref items, polarity, .. }) = it.kind
&& trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait()
&& polarity != ty::ImplPolarity::Negative
&& cleaner.keep_impl(for_, true)
@@ -195,7 +195,7 @@ fn add_deref_target(
// Filter out external items that are not needed
new_items_external.retain(|it| {
if let ImplItem(box Impl { ref for_, ref trait_, ref kind, .. }) = it.kind {
if let ImplItem(Impl { ref for_, ref trait_, ref kind, .. }) = it.kind {
cleaner.keep_impl(
for_,
trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait(),
+4 -1
View File
@@ -69,7 +69,10 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
item_stability
};
let (ItemKind::StrippedItem(box kind) | kind) = &item.kind;
let kind = match &item.kind {
ItemKind::StrippedItem(kind) => kind,
kind => kind,
};
match kind {
ItemKind::ExternCrateItem { .. }
| ItemKind::ImportItem(..)