Rollup merge of #134321 - dtolnay:docassocconst, r=fmease

Hide `= _` as associated constant value inside impl blocks

Closes #134320.

### Before:

<img src="https://github.com/user-attachments/assets/19d28811-45d2-4563-9726-f40c6af411c6" width="300">&nbsp;<img src="https://github.com/user-attachments/assets/1ecf8764-97ce-47f0-87fa-3b174d2fc578" width="300">

### After:

<img src="https://github.com/user-attachments/assets/6408c4ca-b1c4-42e4-884b-248833a4865f" width="300">&nbsp;<img src="https://github.com/user-attachments/assets/df2f6981-16f6-409f-8abb-73c0a4a71d6b" width="300">

r? `@fmease`
This commit is contained in:
Jacob Pratt 2024-12-20 01:36:47 -05:00 committed by GitHub
commit f14d69c853
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 201 additions and 100 deletions

View file

@ -1222,14 +1222,16 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
let local_did = trait_item.owner_id.to_def_id();
cx.with_param_env(local_did, |cx| {
let inner = match trait_item.kind {
hir::TraitItemKind::Const(ty, Some(default)) => AssocConstItem(Box::new(Constant {
generics: enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)),
kind: ConstantKind::Local { def_id: local_did, body: default },
type_: clean_ty(ty, cx),
})),
hir::TraitItemKind::Const(ty, Some(default)) => {
ProvidedAssocConstItem(Box::new(Constant {
generics: enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)),
kind: ConstantKind::Local { def_id: local_did, body: default },
type_: clean_ty(ty, cx),
}))
}
hir::TraitItemKind::Const(ty, None) => {
let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
TyAssocConstItem(generics, Box::new(clean_ty(ty, cx)))
RequiredAssocConstItem(generics, Box::new(clean_ty(ty, cx)))
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Body(body));
@ -1237,7 +1239,7 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => {
let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Names(names));
TyMethodItem(m)
RequiredMethodItem(m)
}
hir::TraitItemKind::Type(bounds, Some(default)) => {
let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
@ -1257,7 +1259,7 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
hir::TraitItemKind::Type(bounds, None) => {
let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect();
TyAssocTypeItem(generics, bounds)
RequiredAssocTypeItem(generics, bounds)
}
};
Item::from_def_id_and_parts(local_did, Some(trait_item.ident.name), inner, cx)
@ -1271,7 +1273,7 @@ pub(crate) fn clean_impl_item<'tcx>(
let local_did = impl_.owner_id.to_def_id();
cx.with_param_env(local_did, |cx| {
let inner = match impl_.kind {
hir::ImplItemKind::Const(ty, expr) => AssocConstItem(Box::new(Constant {
hir::ImplItemKind::Const(ty, expr) => ImplAssocConstItem(Box::new(Constant {
generics: clean_generics(impl_.generics, cx),
kind: ConstantKind::Local { def_id: local_did, body: expr },
type_: clean_ty(ty, cx),
@ -1320,18 +1322,23 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
);
simplify::move_bounds_to_generic_parameters(&mut generics);
let provided = match assoc_item.container {
ty::AssocItemContainer::Impl => true,
ty::AssocItemContainer::Trait => tcx.defaultness(assoc_item.def_id).has_value(),
};
if provided {
AssocConstItem(Box::new(Constant {
match assoc_item.container {
ty::AssocItemContainer::Impl => ImplAssocConstItem(Box::new(Constant {
generics,
kind: ConstantKind::Extern { def_id: assoc_item.def_id },
type_: ty,
}))
} else {
TyAssocConstItem(generics, Box::new(ty))
})),
ty::AssocItemContainer::Trait => {
if tcx.defaultness(assoc_item.def_id).has_value() {
ProvidedAssocConstItem(Box::new(Constant {
generics,
kind: ConstantKind::Extern { def_id: assoc_item.def_id },
type_: ty,
}))
} else {
RequiredAssocConstItem(generics, Box::new(ty))
}
}
}
}
ty::AssocKind::Fn => {
@ -1369,7 +1376,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
};
MethodItem(item, defaultness)
} else {
TyMethodItem(item)
RequiredMethodItem(item)
}
}
ty::AssocKind::Type => {
@ -1486,7 +1493,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
bounds,
)
} else {
TyAssocTypeItem(generics, bounds)
RequiredAssocTypeItem(generics, bounds)
}
} else {
AssocTypeItem(

View file

@ -545,14 +545,14 @@ impl Item {
pub(crate) fn is_associated_type(&self) -> bool {
matches!(self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..)))
}
pub(crate) fn is_ty_associated_type(&self) -> bool {
matches!(self.kind, TyAssocTypeItem(..) | StrippedItem(box TyAssocTypeItem(..)))
pub(crate) fn is_required_associated_type(&self) -> bool {
matches!(self.kind, RequiredAssocTypeItem(..) | StrippedItem(box RequiredAssocTypeItem(..)))
}
pub(crate) fn is_associated_const(&self) -> bool {
matches!(self.kind, AssocConstItem(..) | StrippedItem(box AssocConstItem(..)))
matches!(self.kind, ProvidedAssocConstItem(..) | ImplAssocConstItem(..) | StrippedItem(box (ProvidedAssocConstItem(..) | ImplAssocConstItem(..))))
}
pub(crate) fn is_ty_associated_const(&self) -> bool {
matches!(self.kind, TyAssocConstItem(..) | StrippedItem(box TyAssocConstItem(..)))
pub(crate) fn is_required_associated_const(&self) -> bool {
matches!(self.kind, RequiredAssocConstItem(..) | StrippedItem(box RequiredAssocConstItem(..)))
}
pub(crate) fn is_method(&self) -> bool {
self.type_() == ItemType::Method
@ -669,7 +669,9 @@ impl Item {
asyncness: hir::IsAsync::NotAsync,
}
}
ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) | ItemKind::TyMethodItem(_) => {
ItemKind::FunctionItem(_)
| ItemKind::MethodItem(_, _)
| ItemKind::RequiredMethodItem(_) => {
let def_id = self.def_id().unwrap();
build_fn_header(def_id, tcx, tcx.asyncness(def_id))
}
@ -699,8 +701,13 @@ impl Item {
// Variants always inherit visibility
VariantItem(..) | ImplItem(..) => return None,
// Trait items inherit the trait's visibility
AssocConstItem(..) | TyAssocConstItem(..) | AssocTypeItem(..) | TyAssocTypeItem(..)
| TyMethodItem(..) | MethodItem(..) => {
RequiredAssocConstItem(..)
| ProvidedAssocConstItem(..)
| ImplAssocConstItem(..)
| AssocTypeItem(..)
| RequiredAssocTypeItem(..)
| RequiredMethodItem(..)
| MethodItem(..) => {
let assoc_item = tcx.associated_item(def_id);
let is_trait_item = match assoc_item.container {
ty::AssocItemContainer::Trait => true,
@ -845,10 +852,10 @@ pub(crate) enum ItemKind {
TraitAliasItem(TraitAlias),
ImplItem(Box<Impl>),
/// A required method in a trait declaration meaning it's only a function signature.
TyMethodItem(Box<Function>),
RequiredMethodItem(Box<Function>),
/// A method in a trait impl or a provided method in a trait declaration.
///
/// Compared to [TyMethodItem], it also contains a method body.
/// Compared to [RequiredMethodItem], it also contains a method body.
MethodItem(Box<Function>, Option<hir::Defaultness>),
StructFieldItem(Type),
VariantItem(Variant),
@ -862,14 +869,16 @@ pub(crate) enum ItemKind {
ProcMacroItem(ProcMacro),
PrimitiveItem(PrimitiveType),
/// A required associated constant in a trait declaration.
TyAssocConstItem(Generics, Box<Type>),
RequiredAssocConstItem(Generics, Box<Type>),
ConstantItem(Box<Constant>),
/// An associated constant in a trait impl or a provided one in a trait declaration.
AssocConstItem(Box<Constant>),
/// An associated constant in a trait declaration with provided default value.
ProvidedAssocConstItem(Box<Constant>),
/// An associated constant in an inherent impl or trait impl.
ImplAssocConstItem(Box<Constant>),
/// A required associated type in a trait declaration.
///
/// The bounds may be non-empty if there is a `where` clause.
TyAssocTypeItem(Generics, Vec<GenericBound>),
RequiredAssocTypeItem(Generics, Vec<GenericBound>),
/// An associated type in a trait impl or a provided one in a trait declaration.
AssocTypeItem(Box<TypeAlias>, Vec<GenericBound>),
/// An item that has been stripped by a rustdoc pass
@ -900,7 +909,7 @@ impl ItemKind {
| StaticItem(_)
| ConstantItem(_)
| TraitAliasItem(_)
| TyMethodItem(_)
| RequiredMethodItem(_)
| MethodItem(_, _)
| StructFieldItem(_)
| ForeignFunctionItem(_, _)
@ -909,9 +918,10 @@ impl ItemKind {
| MacroItem(_)
| ProcMacroItem(_)
| PrimitiveItem(_)
| TyAssocConstItem(..)
| AssocConstItem(..)
| TyAssocTypeItem(..)
| RequiredAssocConstItem(..)
| ProvidedAssocConstItem(..)
| ImplAssocConstItem(..)
| RequiredAssocTypeItem(..)
| AssocTypeItem(..)
| StrippedItem(_)
| KeywordItem => [].iter(),

View file

@ -82,7 +82,7 @@ pub(crate) trait DocFolder: Sized {
| StaticItem(_)
| ConstantItem(..)
| TraitAliasItem(_)
| TyMethodItem(_)
| RequiredMethodItem(_)
| MethodItem(_, _)
| StructFieldItem(_)
| ForeignFunctionItem(..)
@ -91,9 +91,10 @@ pub(crate) trait DocFolder: Sized {
| MacroItem(_)
| ProcMacroItem(_)
| PrimitiveItem(_)
| TyAssocConstItem(..)
| AssocConstItem(..)
| TyAssocTypeItem(..)
| RequiredAssocConstItem(..)
| ProvidedAssocConstItem(..)
| ImplAssocConstItem(..)
| RequiredAssocTypeItem(..)
| AssocTypeItem(..)
| KeywordItem => kind,
}

View file

@ -334,12 +334,13 @@ impl DocFolder for CacheBuilder<'_, '_> {
clean::ExternCrateItem { .. }
| clean::ImportItem(..)
| clean::ImplItem(..)
| clean::TyMethodItem(..)
| clean::RequiredMethodItem(..)
| clean::MethodItem(..)
| clean::StructFieldItem(..)
| clean::TyAssocConstItem(..)
| clean::AssocConstItem(..)
| clean::TyAssocTypeItem(..)
| clean::RequiredAssocConstItem(..)
| clean::ProvidedAssocConstItem(..)
| clean::ImplAssocConstItem(..)
| clean::RequiredAssocTypeItem(..)
| clean::AssocTypeItem(..)
| clean::StrippedItem(..)
| clean::KeywordItem => {
@ -443,15 +444,17 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
let item_def_id = item.item_id.as_def_id().unwrap();
let (parent_did, parent_path) = match item.kind {
clean::StrippedItem(..) => return,
clean::AssocConstItem(..) | clean::AssocTypeItem(..)
clean::ProvidedAssocConstItem(..)
| clean::ImplAssocConstItem(..)
| clean::AssocTypeItem(..)
if cache.parent_stack.last().is_some_and(|parent| parent.is_trait_impl()) =>
{
// skip associated items in trait impls
return;
}
clean::TyMethodItem(..)
| clean::TyAssocConstItem(..)
| clean::TyAssocTypeItem(..)
clean::RequiredMethodItem(..)
| clean::RequiredAssocConstItem(..)
| clean::RequiredAssocTypeItem(..)
| clean::StructFieldItem(..)
| clean::VariantItem(..) => {
// Don't index if containing module is stripped (i.e., private),
@ -467,7 +470,10 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
let parent_path = &cache.stack[..cache.stack.len() - 1];
(Some(parent_did), parent_path)
}
clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => {
clean::MethodItem(..)
| clean::ProvidedAssocConstItem(..)
| clean::ImplAssocConstItem(..)
| clean::AssocTypeItem(..) => {
let last = cache.parent_stack.last().expect("parent_stack is empty 2");
let parent_did = match last {
// impl Trait for &T { fn method(self); }

View file

@ -88,7 +88,7 @@ impl<'a> From<&'a clean::Item> for ItemType {
clean::ConstantItem(..) => ItemType::Constant,
clean::TraitItem(..) => ItemType::Trait,
clean::ImplItem(..) => ItemType::Impl,
clean::TyMethodItem(..) => ItemType::TyMethod,
clean::RequiredMethodItem(..) => ItemType::TyMethod,
clean::MethodItem(..) => ItemType::Method,
clean::StructFieldItem(..) => ItemType::StructField,
clean::VariantItem(..) => ItemType::Variant,
@ -96,8 +96,10 @@ impl<'a> From<&'a clean::Item> for ItemType {
clean::ForeignStaticItem(..) => ItemType::Static, // no ForeignStatic
clean::MacroItem(..) => ItemType::Macro,
clean::PrimitiveItem(..) => ItemType::Primitive,
clean::TyAssocConstItem(..) | clean::AssocConstItem(..) => ItemType::AssocConst,
clean::TyAssocTypeItem(..) | clean::AssocTypeItem(..) => ItemType::AssocType,
clean::RequiredAssocConstItem(..)
| clean::ProvidedAssocConstItem(..)
| clean::ImplAssocConstItem(..) => ItemType::AssocConst,
clean::RequiredAssocTypeItem(..) | clean::AssocTypeItem(..) => ItemType::AssocType,
clean::ForeignTypeItem => ItemType::ForeignType,
clean::KeywordItem => ItemType::Keyword,
clean::TraitAliasItem(..) => ItemType::TraitAlias,

View file

@ -836,12 +836,23 @@ fn assoc_href_attr(it: &clean::Item, link: AssocItemLink<'_>, cx: &Context<'_>)
href.map(|href| format!(" href=\"{href}\"")).unwrap_or_default()
}
#[derive(Debug)]
enum AssocConstValue<'a> {
// In trait definitions, it is relevant for the public API whether an
// associated constant comes with a default value, so even if we cannot
// render its value, the presence of a value must be shown using `= _`.
TraitDefault(&'a clean::ConstantKind),
// In impls, there is no need to show `= _`.
Impl(&'a clean::ConstantKind),
None,
}
fn assoc_const(
w: &mut Buffer,
it: &clean::Item,
generics: &clean::Generics,
ty: &clean::Type,
default: Option<&clean::ConstantKind>,
value: AssocConstValue<'_>,
link: AssocItemLink<'_>,
indent: usize,
cx: &Context<'_>,
@ -857,15 +868,20 @@ fn assoc_const(
generics = generics.print(cx),
ty = ty.print(cx),
);
if let Some(default) = default {
w.write_str(" = ");
if let AssocConstValue::TraitDefault(konst) | AssocConstValue::Impl(konst) = value {
// FIXME: `.value()` uses `clean::utils::format_integer_with_underscore_sep` under the
// hood which adds noisy underscores and a type suffix to number literals.
// This hurts readability in this context especially when more complex expressions
// are involved and it doesn't add much of value.
// Find a way to print constants here without all that jazz.
write!(w, "{}", Escape(&default.value(tcx).unwrap_or_else(|| default.expr(tcx))));
let repr = konst.value(tcx).unwrap_or_else(|| konst.expr(tcx));
if match value {
AssocConstValue::TraitDefault(_) => true, // always show
AssocConstValue::Impl(_) => repr != "_", // show if there is a meaningful value to show
AssocConstValue::None => unreachable!(),
} {
write!(w, " = {}", Escape(&repr));
}
}
write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline));
}
@ -1076,33 +1092,43 @@ fn render_assoc_item(
) {
match &item.kind {
clean::StrippedItem(..) => {}
clean::TyMethodItem(m) => {
clean::RequiredMethodItem(m) => {
assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode)
}
clean::MethodItem(m, _) => {
assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode)
}
clean::TyAssocConstItem(generics, ty) => assoc_const(
clean::RequiredAssocConstItem(generics, ty) => assoc_const(
w,
item,
generics,
ty,
None,
AssocConstValue::None,
link,
if parent == ItemType::Trait { 4 } else { 0 },
cx,
),
clean::AssocConstItem(ci) => assoc_const(
clean::ProvidedAssocConstItem(ci) => assoc_const(
w,
item,
&ci.generics,
&ci.type_,
Some(&ci.kind),
AssocConstValue::TraitDefault(&ci.kind),
link,
if parent == ItemType::Trait { 4 } else { 0 },
cx,
),
clean::TyAssocTypeItem(ref generics, ref bounds) => assoc_type(
clean::ImplAssocConstItem(ci) => assoc_const(
w,
item,
&ci.generics,
&ci.type_,
AssocConstValue::Impl(&ci.kind),
link,
if parent == ItemType::Trait { 4 } else { 0 },
cx,
),
clean::RequiredAssocTypeItem(ref generics, ref bounds) => assoc_type(
w,
item,
generics,
@ -1384,7 +1410,7 @@ fn render_deref_methods(
fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool {
let self_type_opt = match item.kind {
clean::MethodItem(ref method, _) => method.decl.receiver_type(),
clean::TyMethodItem(ref method) => method.decl.receiver_type(),
clean::RequiredMethodItem(ref method) => method.decl.receiver_type(),
_ => None,
};
@ -1660,7 +1686,7 @@ fn render_impl(
write!(w, "<details class=\"toggle{method_toggle_class}\" open><summary>");
}
match &item.kind {
clean::MethodItem(..) | clean::TyMethodItem(_) => {
clean::MethodItem(..) | clean::RequiredMethodItem(_) => {
// Only render when the method is not static or we allow static methods
if render_method_item {
let id = cx.derive_id(format!("{item_type}.{name}"));
@ -1690,7 +1716,7 @@ fn render_impl(
w.write_str("</h4></section>");
}
}
clean::TyAssocConstItem(ref generics, ref ty) => {
clean::RequiredAssocConstItem(ref generics, ref ty) => {
let source_id = format!("{item_type}.{name}");
let id = cx.derive_id(&source_id);
write!(w, "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">");
@ -1705,14 +1731,14 @@ fn render_impl(
item,
generics,
ty,
None,
AssocConstValue::None,
link.anchor(if trait_.is_some() { &source_id } else { &id }),
0,
cx,
);
w.write_str("</h4></section>");
}
clean::AssocConstItem(ci) => {
clean::ProvidedAssocConstItem(ci) | clean::ImplAssocConstItem(ci) => {
let source_id = format!("{item_type}.{name}");
let id = cx.derive_id(&source_id);
write!(w, "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">");
@ -1727,14 +1753,18 @@ fn render_impl(
item,
&ci.generics,
&ci.type_,
Some(&ci.kind),
match item.kind {
clean::ProvidedAssocConstItem(_) => AssocConstValue::TraitDefault(&ci.kind),
clean::ImplAssocConstItem(_) => AssocConstValue::Impl(&ci.kind),
_ => unreachable!(),
},
link.anchor(if trait_.is_some() { &source_id } else { &id }),
0,
cx,
);
w.write_str("</h4></section>");
}
clean::TyAssocTypeItem(ref generics, ref bounds) => {
clean::RequiredAssocTypeItem(ref generics, ref bounds) => {
let source_id = format!("{item_type}.{name}");
let id = cx.derive_id(&source_id);
write!(w, "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">");
@ -1809,11 +1839,13 @@ fn render_impl(
if !impl_.is_negative_trait_impl() {
for trait_item in &impl_.items {
match trait_item.kind {
clean::MethodItem(..) | clean::TyMethodItem(_) => methods.push(trait_item),
clean::TyAssocTypeItem(..) | clean::AssocTypeItem(..) => {
clean::MethodItem(..) | clean::RequiredMethodItem(_) => methods.push(trait_item),
clean::RequiredAssocTypeItem(..) | clean::AssocTypeItem(..) => {
assoc_types.push(trait_item)
}
clean::TyAssocConstItem(..) | clean::AssocConstItem(_) => {
clean::RequiredAssocConstItem(..)
| clean::ProvidedAssocConstItem(_)
| clean::ImplAssocConstItem(_) => {
// We render it directly since they're supposed to come first.
doc_impl_item(
&mut default_impl_items,

View file

@ -651,9 +651,11 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) {
let tcx = cx.tcx();
let bounds = bounds(&t.bounds, false, cx);
let required_types = t.items.iter().filter(|m| m.is_ty_associated_type()).collect::<Vec<_>>();
let required_types =
t.items.iter().filter(|m| m.is_required_associated_type()).collect::<Vec<_>>();
let provided_types = t.items.iter().filter(|m| m.is_associated_type()).collect::<Vec<_>>();
let required_consts = t.items.iter().filter(|m| m.is_ty_associated_const()).collect::<Vec<_>>();
let required_consts =
t.items.iter().filter(|m| m.is_required_associated_const()).collect::<Vec<_>>();
let provided_consts = t.items.iter().filter(|m| m.is_associated_const()).collect::<Vec<_>>();
let required_methods = t.items.iter().filter(|m| m.is_ty_method()).collect::<Vec<_>>();
let provided_methods = t.items.iter().filter(|m| m.is_method()).collect::<Vec<_>>();

View file

@ -837,7 +837,7 @@ pub(crate) fn get_function_type_for_search(
clean::ForeignFunctionItem(ref f, _)
| clean::FunctionItem(ref f)
| clean::MethodItem(ref f, _)
| clean::TyMethodItem(ref f) => {
| clean::RequiredMethodItem(ref f) => {
get_fn_inputs_and_outputs(f, tcx, impl_or_trait_generics, cache)
}
_ => return None,
@ -1207,10 +1207,11 @@ fn simplify_fn_type<'a, 'tcx>(
&& let Type::Path { path } = arg
&& let def_id = path.def_id()
&& let Some(trait_) = cache.traits.get(&def_id)
&& trait_.items.iter().any(|at| at.is_ty_associated_type())
&& trait_.items.iter().any(|at| at.is_required_associated_type())
{
for assoc_ty in &trait_.items {
if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &assoc_ty.kind
if let clean::ItemKind::RequiredAssocTypeItem(_generics, bounds) =
&assoc_ty.kind
&& let Some(name) = assoc_ty.name
{
let idx = -isize::try_from(rgen.len() + 1).unwrap();

View file

@ -282,10 +282,10 @@ fn sidebar_trait<'a>(
res
}
let req_assoc = filter_items(&t.items, |m| m.is_ty_associated_type(), "associatedtype");
let req_assoc = filter_items(&t.items, |m| m.is_required_associated_type(), "associatedtype");
let prov_assoc = filter_items(&t.items, |m| m.is_associated_type(), "associatedtype");
let req_assoc_const =
filter_items(&t.items, |m| m.is_ty_associated_const(), "associatedconstant");
filter_items(&t.items, |m| m.is_required_associated_const(), "associatedconstant");
let prov_assoc_const =
filter_items(&t.items, |m| m.is_associated_const(), "associatedconstant");
let req_method = filter_items(&t.items, |m| m.is_ty_method(), "tymethod");

View file

@ -319,7 +319,9 @@ fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum {
TraitItem(t) => ItemEnum::Trait((*t).into_json(renderer)),
TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_json(renderer)),
MethodItem(m, _) => ItemEnum::Function(from_function(m, true, header.unwrap(), renderer)),
TyMethodItem(m) => ItemEnum::Function(from_function(m, false, header.unwrap(), renderer)),
RequiredMethodItem(m) => {
ItemEnum::Function(from_function(m, false, header.unwrap(), renderer))
}
ImplItem(i) => ItemEnum::Impl((*i).into_json(renderer)),
StaticItem(s) => ItemEnum::Static(convert_static(s, rustc_hir::Safety::Safe, renderer)),
ForeignStaticItem(s, safety) => ItemEnum::Static(convert_static(s, safety, renderer)),
@ -339,15 +341,15 @@ fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum {
})
}
// FIXME(generic_const_items): Add support for generic associated consts.
TyAssocConstItem(_generics, ty) => {
RequiredAssocConstItem(_generics, ty) => {
ItemEnum::AssocConst { type_: (*ty).into_json(renderer), value: None }
}
// FIXME(generic_const_items): Add support for generic associated consts.
AssocConstItem(ci) => ItemEnum::AssocConst {
ProvidedAssocConstItem(ci) | ImplAssocConstItem(ci) => ItemEnum::AssocConst {
type_: ci.type_.into_json(renderer),
value: Some(ci.kind.expr(renderer.tcx)),
},
TyAssocTypeItem(g, b) => ItemEnum::AssocType {
RequiredAssocTypeItem(g, b) => ItemEnum::AssocType {
generics: g.into_json(renderer),
bounds: b.into_json(renderer),
type_: None,

View file

@ -72,10 +72,11 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
| clean::ForeignFunctionItem(..)
| clean::ForeignStaticItem(..)
| clean::ForeignTypeItem
| clean::AssocConstItem(..)
| clean::AssocTypeItem(..)
| clean::TyAssocConstItem(..)
| clean::TyAssocTypeItem(..)
| clean::RequiredAssocConstItem(..)
| clean::ProvidedAssocConstItem(..)
| clean::ImplAssocConstItem(..)
| clean::RequiredAssocTypeItem(..)
// check for trait impl
| clean::ImplItem(box clean::Impl { trait_: Some(_), .. })
)

View file

@ -67,11 +67,12 @@ impl DocFolder for StabilityPropagator<'_, '_> {
// Don't inherit the parent's stability for these items, because they
// are potentially accessible even if the parent is more unstable.
ItemKind::ImplItem(..)
| ItemKind::TyMethodItem(..)
| ItemKind::RequiredMethodItem(..)
| ItemKind::MethodItem(..)
| ItemKind::TyAssocConstItem(..)
| ItemKind::AssocConstItem(..)
| ItemKind::TyAssocTypeItem(..)
| ItemKind::RequiredAssocConstItem(..)
| ItemKind::ProvidedAssocConstItem(..)
| ItemKind::ImplAssocConstItem(..)
| ItemKind::RequiredAssocTypeItem(..)
| ItemKind::AssocTypeItem(..)
| ItemKind::PrimitiveItem(..)
| ItemKind::KeywordItem => own_stability,

View file

@ -79,7 +79,10 @@ impl DocFolder for Stripper<'_, '_> {
}
}
clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => {
clean::MethodItem(..)
| clean::ProvidedAssocConstItem(..)
| clean::ImplAssocConstItem(..)
| clean::AssocTypeItem(..) => {
let item_id = i.item_id;
if item_id.is_local()
&& !self.effective_visibilities.is_reachable(self.tcx, item_id.expect_def_id())
@ -118,7 +121,9 @@ impl DocFolder for Stripper<'_, '_> {
clean::ImplItem(..) => {}
// tymethods etc. have no control over privacy
clean::TyMethodItem(..) | clean::TyAssocConstItem(..) | clean::TyAssocTypeItem(..) => {}
clean::RequiredMethodItem(..)
| clean::RequiredAssocConstItem(..)
| clean::RequiredAssocTypeItem(..) => {}
// Proc-macros are always public
clean::ProcMacroItem(..) => {}

View file

@ -35,7 +35,7 @@ pub(crate) trait DocVisitor<'a>: Sized {
| StaticItem(_)
| ConstantItem(..)
| TraitAliasItem(_)
| TyMethodItem(_)
| RequiredMethodItem(_)
| MethodItem(_, _)
| StructFieldItem(_)
| ForeignFunctionItem(..)
@ -44,9 +44,10 @@ pub(crate) trait DocVisitor<'a>: Sized {
| MacroItem(_)
| ProcMacroItem(_)
| PrimitiveItem(_)
| TyAssocConstItem(..)
| AssocConstItem(..)
| TyAssocTypeItem(..)
| RequiredAssocConstItem(..)
| ProvidedAssocConstItem(..)
| ImplAssocConstItem(..)
| RequiredAssocTypeItem(..)
| AssocTypeItem(..)
| KeywordItem => {}
}

View file

@ -0,0 +1,30 @@
pub struct Struct {
_private: (),
}
pub trait Trait {
//@ has assoc_consts_underscore/trait.Trait.html '//pre[@class="rust item-decl"]' \
// 'const REQUIRED: Struct;'
//@ !has - '//*[@id="associatedconstant.REQUIRED"]' 'const REQUIRED: Struct = _'
//@ has - '//*[@id="associatedconstant.REQUIRED"]' 'const REQUIRED: Struct'
const REQUIRED: Struct;
//@ has - '//pre[@class="rust item-decl"]' 'const OPTIONAL: Struct = _;'
//@ has - '//*[@id="associatedconstant.OPTIONAL"]' 'const OPTIONAL: Struct = _'
const OPTIONAL: Struct = Struct { _private: () };
}
impl Trait for Struct {
//@ !has assoc_consts_underscore/struct.Struct.html '//*[@id="associatedconstant.REQUIRED"]' \
// 'const REQUIRED: Struct = _'
//@ has - '//*[@id="associatedconstant.REQUIRED"]' 'const REQUIRED: Struct'
const REQUIRED: Struct = Struct { _private: () };
//@ !has - '//*[@id="associatedconstant.OPTIONAL"]' 'const OPTIONAL: Struct = _'
//@ has - '//*[@id="associatedconstant.OPTIONAL"]' 'const OPTIONAL: Struct'
const OPTIONAL: Struct = Struct { _private: () };
}
impl Struct {
//@ !has - '//*[@id="associatedconstant.INHERENT"]' 'const INHERENT: Struct = _'
//@ has - '//*[@id="associatedconstant.INHERENT"]' 'const INHERENT: Struct'
pub const INHERENT: Struct = Struct { _private: () };
}

View file

@ -14,6 +14,6 @@ impl<const B: Word> Repr<B> {
// If we change back to rendering the value of consts, check this doesn't add
// a <b> tag, but escapes correctly
//@ has foo/struct.Repr.html '//section[@id="associatedconstant.BASE"]/h4' '= _'
//@ !has foo/struct.Repr.html '//section[@id="associatedconstant.BASE"]/h4' '='
pub const BASE: IBig = base_as_ibig::<B>();
}