Skip to content

Commit 0ec00c0

Browse files
authored
Rollup merge of #95316 - fmease:rustdoc-discr-req-prov-assoc-consts-tys, r=notriddle,GuillaumeGomez
Rustdoc: Discriminate required and provided associated constants and types Currently, rustdoc merely separates required and provided associated _functions_ (i.e. methods). This PR extends this to constants (fixes #94652) and types. This makes the documentation of all three kinds of associated items more alike and consistent. As an aside, associated types may actually be provided / have a default when users enable the unstable feature `associated_type_defaults`. | Before | After | |---|---| | ![image](https://user-images.githubusercontent.com/14913065/160631832-d5862d13-b395-4d86-b45c-3873ffd4cd4e.png) | ![image](https://user-images.githubusercontent.com/14913065/160631903-33909a03-b6ee-4d75-9cbc-d188f7f8602e.png) | | ![image](https://user-images.githubusercontent.com/14913065/160632173-040d4139-76f4-4410-851b-d8c1cef014d2.png) | ![image](https://user-images.githubusercontent.com/14913065/160632233-6fd3fe73-cadc-4291-b104-59d2e45366a6.png) | ### `clean::types::ItemKind` modification * `ItemKind::TypedefItem(.., true)` → `ItemKind::AssocTypeItem(..)` * `ItemKind::TypedefItem(.., false)` → `ItemKind::TypedefItem(..)` Further, I added `ItemKind::TyAssoc{Const,Type}Item`, the “required” variant of `ItemKind::Assoc{Const,Type}Item`, analogous to `ItemKind::TyMethodItem` with `ItemKind::MethodItem`. These new variants don't contain new information really, they are just the result of me getting rid of the `Option<_>` field in `AssocConstItem` and `AssocTypeItem`. **Goal**: Make associated items more consistent. Originally I thought modifying `ItemKind` was necessary to achieve the new functionality of this PR but in retrospect, it does not. If you don't like the changes to `ItemKind`, I think I _can_ get rid of them. This change is the root cause of those tiny changes in a lot of different files. ### Concerns and Open Questions * **breaking changes** to hyperlinks: Some heading IDs change: * `associated-const` (sic!) -> `{provided,required}-associated-consts` * `associated-types` -> `{provided,required}-associated-types` * **verbosity** of the headings _{Required,Provided} Associated {Constants,Types}_ * For some files, I am not sure if the changes I made are correct. So please take extra care when reviewing `conversions.rs` (conversion to JSON), `cache.rs`/`fold_item`, `stripper.rs`/`fold_item`, `check_doc_test_visibility.rs`/`should_have_doc_example`, `collect_intra_doc_links.rs`/`from_assoc_item` * JSON output: I still map `AssocTypeItem`s to `Typedef` etc. (FIXME)
2 parents 52ca603 + 8de453a commit 0ec00c0

22 files changed

+401
-243
lines changed

src/librustdoc/clean/inline.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ crate fn try_inline(
7979
Res::Def(DefKind::TyAlias, did) => {
8080
record_extern_fqn(cx, did, ItemType::Typedef);
8181
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
82-
clean::TypedefItem(build_type_alias(cx, did), false)
82+
clean::TypedefItem(build_type_alias(cx, did))
8383
}
8484
Res::Def(DefKind::Enum, did) => {
8585
record_extern_fqn(cx, did, ItemType::Enum);

src/librustdoc/clean/mod.rs

+51-34
Original file line numberDiff line numberDiff line change
@@ -964,11 +964,11 @@ impl Clean<Item> for hir::TraitItem<'_> {
964964
let local_did = self.def_id.to_def_id();
965965
cx.with_param_env(local_did, |cx| {
966966
let inner = match self.kind {
967-
hir::TraitItemKind::Const(ref ty, default) => {
968-
let default =
969-
default.map(|e| ConstantKind::Local { def_id: local_did, body: e });
970-
AssocConstItem(ty.clean(cx), default)
971-
}
967+
hir::TraitItemKind::Const(ref ty, Some(default)) => AssocConstItem(
968+
ty.clean(cx),
969+
ConstantKind::Local { def_id: local_did, body: default },
970+
),
971+
hir::TraitItemKind::Const(ref ty, None) => TyAssocConstItem(ty.clean(cx)),
972972
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
973973
let m = clean_function(cx, sig, &self.generics, body);
974974
MethodItem(m, None)
@@ -983,11 +983,19 @@ impl Clean<Item> for hir::TraitItem<'_> {
983983
});
984984
TyMethodItem(Function { decl, generics })
985985
}
986-
hir::TraitItemKind::Type(bounds, ref default) => {
986+
hir::TraitItemKind::Type(bounds, Some(default)) => {
987+
let generics = enter_impl_trait(cx, |cx| self.generics.clean(cx));
988+
let bounds = bounds.iter().filter_map(|x| x.clean(cx)).collect();
989+
let item_type = hir_ty_to_ty(cx.tcx, default).clean(cx);
990+
AssocTypeItem(
991+
Typedef { type_: default.clean(cx), generics, item_type: Some(item_type) },
992+
bounds,
993+
)
994+
}
995+
hir::TraitItemKind::Type(bounds, None) => {
987996
let generics = enter_impl_trait(cx, |cx| self.generics.clean(cx));
988997
let bounds = bounds.iter().filter_map(|x| x.clean(cx)).collect();
989-
let default = default.map(|t| t.clean(cx));
990-
AssocTypeItem(Box::new(generics), bounds, default)
998+
TyAssocTypeItem(Box::new(generics), bounds)
991999
}
9921000
};
9931001
let what_rustc_thinks =
@@ -1004,7 +1012,7 @@ impl Clean<Item> for hir::ImplItem<'_> {
10041012
cx.with_param_env(local_did, |cx| {
10051013
let inner = match self.kind {
10061014
hir::ImplItemKind::Const(ref ty, expr) => {
1007-
let default = Some(ConstantKind::Local { def_id: local_did, body: expr });
1015+
let default = ConstantKind::Local { def_id: local_did, body: expr };
10081016
AssocConstItem(ty.clean(cx), default)
10091017
}
10101018
hir::ImplItemKind::Fn(ref sig, body) => {
@@ -1016,7 +1024,10 @@ impl Clean<Item> for hir::ImplItem<'_> {
10161024
let type_ = hir_ty.clean(cx);
10171025
let generics = self.generics.clean(cx);
10181026
let item_type = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
1019-
TypedefItem(Typedef { type_, generics, item_type: Some(item_type) }, true)
1027+
AssocTypeItem(
1028+
Typedef { type_, generics, item_type: Some(item_type) },
1029+
Vec::new(),
1030+
)
10201031
}
10211032
};
10221033

@@ -1041,13 +1052,17 @@ impl Clean<Item> for ty::AssocItem {
10411052
let tcx = cx.tcx;
10421053
let kind = match self.kind {
10431054
ty::AssocKind::Const => {
1044-
let ty = tcx.type_of(self.def_id);
1045-
let default = if self.defaultness.has_value() {
1046-
Some(ConstantKind::Extern { def_id: self.def_id })
1047-
} else {
1048-
None
1055+
let ty = tcx.type_of(self.def_id).clean(cx);
1056+
1057+
let provided = match self.container {
1058+
ty::ImplContainer(_) => true,
1059+
ty::TraitContainer(_) => self.defaultness.has_value(),
10491060
};
1050-
AssocConstItem(ty.clean(cx), default)
1061+
if provided {
1062+
AssocConstItem(ty, ConstantKind::Extern { def_id: self.def_id })
1063+
} else {
1064+
TyAssocConstItem(ty)
1065+
}
10511066
}
10521067
ty::AssocKind::Fn => {
10531068
let generics = clean_ty_generics(
@@ -1181,23 +1196,28 @@ impl Clean<Item> for ty::AssocItem {
11811196
None => bounds.push(GenericBound::maybe_sized(cx)),
11821197
}
11831198

1184-
let ty = if self.defaultness.has_value() {
1185-
Some(tcx.type_of(self.def_id))
1199+
if self.defaultness.has_value() {
1200+
AssocTypeItem(
1201+
Typedef {
1202+
type_: tcx.type_of(self.def_id).clean(cx),
1203+
generics,
1204+
// FIXME: should we obtain the Type from HIR and pass it on here?
1205+
item_type: None,
1206+
},
1207+
bounds,
1208+
)
11861209
} else {
1187-
None
1188-
};
1189-
1190-
AssocTypeItem(Box::new(generics), bounds, ty.map(|t| t.clean(cx)))
1210+
TyAssocTypeItem(Box::new(generics), bounds)
1211+
}
11911212
} else {
11921213
// FIXME: when could this happen? Associated items in inherent impls?
1193-
let type_ = tcx.type_of(self.def_id).clean(cx);
1194-
TypedefItem(
1214+
AssocTypeItem(
11951215
Typedef {
1196-
type_,
1216+
type_: tcx.type_of(self.def_id).clean(cx),
11971217
generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
11981218
item_type: None,
11991219
},
1200-
true,
1220+
Vec::new(),
12011221
)
12021222
}
12031223
}
@@ -1837,14 +1857,11 @@ fn clean_maybe_renamed_item(
18371857
ItemKind::TyAlias(hir_ty, ref generics) => {
18381858
let rustdoc_ty = hir_ty.clean(cx);
18391859
let ty = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
1840-
TypedefItem(
1841-
Typedef {
1842-
type_: rustdoc_ty,
1843-
generics: generics.clean(cx),
1844-
item_type: Some(ty),
1845-
},
1846-
false,
1847-
)
1860+
TypedefItem(Typedef {
1861+
type_: rustdoc_ty,
1862+
generics: generics.clean(cx),
1863+
item_type: Some(ty),
1864+
})
18481865
}
18491866
ItemKind::Enum(ref def, ref generics) => EnumItem(Enum {
18501867
variants: def.variants.iter().map(|v| v.clean(cx)).collect(),

src/librustdoc/clean/types.rs

+24-11
Original file line numberDiff line numberDiff line change
@@ -577,10 +577,16 @@ impl Item {
577577
self.type_() == ItemType::Variant
578578
}
579579
crate fn is_associated_type(&self) -> bool {
580-
self.type_() == ItemType::AssocType
580+
matches!(&*self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..)))
581+
}
582+
crate fn is_ty_associated_type(&self) -> bool {
583+
matches!(&*self.kind, TyAssocTypeItem(..) | StrippedItem(box TyAssocTypeItem(..)))
581584
}
582585
crate fn is_associated_const(&self) -> bool {
583-
self.type_() == ItemType::AssocConst
586+
matches!(&*self.kind, AssocConstItem(..) | StrippedItem(box AssocConstItem(..)))
587+
}
588+
crate fn is_ty_associated_const(&self) -> bool {
589+
matches!(&*self.kind, TyAssocConstItem(..) | StrippedItem(box TyAssocConstItem(..)))
584590
}
585591
crate fn is_method(&self) -> bool {
586592
self.type_() == ItemType::Method
@@ -726,17 +732,18 @@ crate enum ItemKind {
726732
EnumItem(Enum),
727733
FunctionItem(Function),
728734
ModuleItem(Module),
729-
TypedefItem(Typedef, bool /* is associated type */),
735+
TypedefItem(Typedef),
730736
OpaqueTyItem(OpaqueTy),
731737
StaticItem(Static),
732738
ConstantItem(Constant),
733739
TraitItem(Trait),
734740
TraitAliasItem(TraitAlias),
735741
ImplItem(Impl),
736-
/// A method signature only. Used for required methods in traits (ie,
737-
/// non-default-methods).
742+
/// A required method in a trait declaration meaning it's only a function signature.
738743
TyMethodItem(Function),
739-
/// A method with a body.
744+
/// A method in a trait impl or a provided method in a trait declaration.
745+
///
746+
/// Compared to [TyMethodItem], it also contains a method body.
740747
MethodItem(Function, Option<hir::Defaultness>),
741748
StructFieldItem(Type),
742749
VariantItem(Variant),
@@ -749,12 +756,16 @@ crate enum ItemKind {
749756
MacroItem(Macro),
750757
ProcMacroItem(ProcMacro),
751758
PrimitiveItem(PrimitiveType),
752-
AssocConstItem(Type, Option<ConstantKind>),
753-
/// An associated item in a trait or trait impl.
759+
/// A required associated constant in a trait declaration.
760+
TyAssocConstItem(Type),
761+
/// An associated associated constant in a trait impl or a provided one in a trait declaration.
762+
AssocConstItem(Type, ConstantKind),
763+
/// A required associated type in a trait declaration.
754764
///
755765
/// The bounds may be non-empty if there is a `where` clause.
756-
/// The `Option<Type>` is the default concrete type (e.g. `trait Trait { type Target = usize; }`)
757-
AssocTypeItem(Box<Generics>, Vec<GenericBound>, Option<Type>),
766+
TyAssocTypeItem(Box<Generics>, Vec<GenericBound>),
767+
/// An associated type in a trait impl or a provided one in a trait declaration.
768+
AssocTypeItem(Typedef, Vec<GenericBound>),
758769
/// An item that has been stripped by a rustdoc pass
759770
StrippedItem(Box<ItemKind>),
760771
KeywordItem(Symbol),
@@ -776,7 +787,7 @@ impl ItemKind {
776787
ExternCrateItem { .. }
777788
| ImportItem(_)
778789
| FunctionItem(_)
779-
| TypedefItem(_, _)
790+
| TypedefItem(_)
780791
| OpaqueTyItem(_)
781792
| StaticItem(_)
782793
| ConstantItem(_)
@@ -791,7 +802,9 @@ impl ItemKind {
791802
| MacroItem(_)
792803
| ProcMacroItem(_)
793804
| PrimitiveItem(_)
805+
| TyAssocConstItem(_)
794806
| AssocConstItem(_, _)
807+
| TyAssocTypeItem(..)
795808
| AssocTypeItem(..)
796809
| StrippedItem(_)
797810
| KeywordItem(_) => [].iter(),

src/librustdoc/clean/utils.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ crate fn build_deref_target_impls(cx: &mut DocContext<'_>, items: &[Item], ret:
178178

179179
for item in items {
180180
let target = match *item.kind {
181-
ItemKind::TypedefItem(ref t, true) => &t.type_,
181+
ItemKind::AssocTypeItem(ref t, _) => &t.type_,
182182
_ => continue,
183183
};
184184

src/librustdoc/fold.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ crate trait DocFolder: Sized {
7171
ExternCrateItem { src: _ }
7272
| ImportItem(_)
7373
| FunctionItem(_)
74-
| TypedefItem(_, _)
74+
| TypedefItem(_)
7575
| OpaqueTyItem(_)
7676
| StaticItem(_)
7777
| ConstantItem(_)
@@ -85,7 +85,9 @@ crate trait DocFolder: Sized {
8585
| MacroItem(_)
8686
| ProcMacroItem(_)
8787
| PrimitiveItem(_)
88-
| AssocConstItem(_, _)
88+
| TyAssocConstItem(..)
89+
| AssocConstItem(..)
90+
| TyAssocTypeItem(..)
8991
| AssocTypeItem(..)
9092
| KeywordItem(_) => kind,
9193
}

src/librustdoc/formats/cache.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -242,14 +242,15 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
242242
if let Some(ref s) = item.name {
243243
let (parent, is_inherent_impl_item) = match *item.kind {
244244
clean::StrippedItem(..) => ((None, None), false),
245-
clean::AssocConstItem(..) | clean::TypedefItem(_, true)
245+
clean::AssocConstItem(..) | clean::AssocTypeItem(..)
246246
if self.cache.parent_is_trait_impl =>
247247
{
248248
// skip associated items in trait impls
249249
((None, None), false)
250250
}
251-
clean::AssocTypeItem(..)
252-
| clean::TyMethodItem(..)
251+
clean::TyMethodItem(..)
252+
| clean::TyAssocConstItem(..)
253+
| clean::TyAssocTypeItem(..)
253254
| clean::StructFieldItem(..)
254255
| clean::VariantItem(..) => (
255256
(
@@ -258,7 +259,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
258259
),
259260
false,
260261
),
261-
clean::MethodItem(..) | clean::AssocConstItem(..) => {
262+
clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => {
262263
if self.cache.parent_stack.is_empty() {
263264
((None, None), false)
264265
} else {
@@ -373,7 +374,9 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
373374
| clean::TyMethodItem(..)
374375
| clean::MethodItem(..)
375376
| clean::StructFieldItem(..)
377+
| clean::TyAssocConstItem(..)
376378
| clean::AssocConstItem(..)
379+
| clean::TyAssocTypeItem(..)
377380
| clean::AssocTypeItem(..)
378381
| clean::StrippedItem(..)
379382
| clean::KeywordItem(..) => {

src/librustdoc/formats/item_type.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::clean;
1414
/// The search index uses item types encoded as smaller numbers which equal to
1515
/// discriminants. JavaScript then is used to decode them into the original value.
1616
/// Consequently, every change to this type should be synchronized to
17-
/// the `itemTypes` mapping table in `html/static/main.js`.
17+
/// the `itemTypes` mapping table in `html/static/js/search.js`.
1818
///
1919
/// In addition, code in `html::render` uses this enum to generate CSS classes, page prefixes, and
2020
/// module headings. If you are adding to this enum and want to ensure that the sidebar also prints
@@ -89,8 +89,8 @@ impl<'a> From<&'a clean::Item> for ItemType {
8989
clean::ForeignStaticItem(..) => ItemType::Static, // no ForeignStatic
9090
clean::MacroItem(..) => ItemType::Macro,
9191
clean::PrimitiveItem(..) => ItemType::Primitive,
92-
clean::AssocConstItem(..) => ItemType::AssocConst,
93-
clean::AssocTypeItem(..) => ItemType::AssocType,
92+
clean::TyAssocConstItem(..) | clean::AssocConstItem(..) => ItemType::AssocConst,
93+
clean::TyAssocTypeItem(..) | clean::AssocTypeItem(..) => ItemType::AssocType,
9494
clean::ForeignTypeItem => ItemType::ForeignType,
9595
clean::KeywordItem(..) => ItemType::Keyword,
9696
clean::TraitAliasItem(..) => ItemType::TraitAlias,

src/librustdoc/html/format.rs

+15
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,21 @@ crate enum HrefError {
527527
/// This item is known to rustdoc, but from a crate that does not have documentation generated.
528528
///
529529
/// This can only happen for non-local items.
530+
///
531+
/// # Example
532+
///
533+
/// Crate `a` defines a public trait and crate `b` – the target crate that depends on `a` –
534+
/// implements it for a local type.
535+
/// We document `b` but **not** `a` (we only _build_ the latter – with `rustc`):
536+
///
537+
/// ```sh
538+
/// rustc a.rs --crate-type=lib
539+
/// rustdoc b.rs --crate-type=lib --extern=a=liba.rlib
540+
/// ```
541+
///
542+
/// Now, the associated items in the trait impl want to link to the corresponding item in the
543+
/// trait declaration (see `html::render::assoc_href_attr`) but it's not available since their
544+
/// *documentation (was) not built*.
530545
DocumentationNotBuilt,
531546
/// This can only happen for non-local items when `--document-private-items` is not passed.
532547
Private,

src/librustdoc/html/markdown.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1452,8 +1452,10 @@ fn init_id_map() -> FxHashMap<String, usize> {
14521452
map.insert("trait-implementations".to_owned(), 1);
14531453
map.insert("synthetic-implementations".to_owned(), 1);
14541454
map.insert("blanket-implementations".to_owned(), 1);
1455-
map.insert("associated-types".to_owned(), 1);
1456-
map.insert("associated-const".to_owned(), 1);
1455+
map.insert("required-associated-types".to_owned(), 1);
1456+
map.insert("provided-associated-types".to_owned(), 1);
1457+
map.insert("provided-associated-consts".to_owned(), 1);
1458+
map.insert("required-associated-consts".to_owned(), 1);
14571459
map.insert("required-methods".to_owned(), 1);
14581460
map.insert("provided-methods".to_owned(), 1);
14591461
map.insert("implementors".to_owned(), 1);

0 commit comments

Comments
 (0)