Rollup merge of #139943 - fmease:rustdoc-ixcre-trait-aliases, r=GuillaumeGomez
rustdoc: Support inlined cross-crate re-exported trait aliases Previously we'd just drop them. As a result of this PR, [`core::ptr::Thin`](https://doc.rust-lang.org/nightly/core/ptr/traitalias.Thin.html) will be admitted into the `std` façade! Also, render the where clause *after* the bounds / the `=`, not before them, as it should be. r? rustdoc
This commit is contained in:
commit
7a4525c883
8 changed files with 122 additions and 64 deletions
|
@ -67,9 +67,13 @@ pub(crate) fn try_inline(
|
|||
record_extern_fqn(cx, did, ItemType::Trait);
|
||||
cx.with_param_env(did, |cx| {
|
||||
build_impls(cx, did, attrs_without_docs, &mut ret);
|
||||
clean::TraitItem(Box::new(build_external_trait(cx, did)))
|
||||
clean::TraitItem(Box::new(build_trait(cx, did)))
|
||||
})
|
||||
}
|
||||
Res::Def(DefKind::TraitAlias, did) => {
|
||||
record_extern_fqn(cx, did, ItemType::TraitAlias);
|
||||
cx.with_param_env(did, |cx| clean::TraitAliasItem(build_trait_alias(cx, did)))
|
||||
}
|
||||
Res::Def(DefKind::Fn, did) => {
|
||||
record_extern_fqn(cx, did, ItemType::Function);
|
||||
cx.with_param_env(did, |cx| {
|
||||
|
@ -251,7 +255,7 @@ pub(crate) fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemT
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean::Trait {
|
||||
pub(crate) fn build_trait(cx: &mut DocContext<'_>, did: DefId) -> clean::Trait {
|
||||
let trait_items = cx
|
||||
.tcx
|
||||
.associated_items(did)
|
||||
|
@ -263,11 +267,18 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
|
|||
let predicates = cx.tcx.predicates_of(did);
|
||||
let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
|
||||
let generics = filter_non_trait_generics(did, generics);
|
||||
let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
|
||||
let (generics, supertrait_bounds) = separate_self_bounds(generics);
|
||||
clean::Trait { def_id: did, generics, items: trait_items, bounds: supertrait_bounds }
|
||||
}
|
||||
|
||||
pub(crate) fn build_function(cx: &mut DocContext<'_>, def_id: DefId) -> Box<clean::Function> {
|
||||
fn build_trait_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::TraitAlias {
|
||||
let predicates = cx.tcx.predicates_of(did);
|
||||
let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
|
||||
let (generics, bounds) = separate_self_bounds(generics);
|
||||
clean::TraitAlias { generics, bounds }
|
||||
}
|
||||
|
||||
pub(super) fn build_function(cx: &mut DocContext<'_>, def_id: DefId) -> Box<clean::Function> {
|
||||
let sig = cx.tcx.fn_sig(def_id).instantiate_identity();
|
||||
// The generics need to be cleaned before the signature.
|
||||
let mut generics =
|
||||
|
@ -788,12 +799,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
|
|||
g
|
||||
}
|
||||
|
||||
/// Supertrait bounds for a trait are also listed in the generics coming from
|
||||
/// the metadata for a crate, so we want to separate those out and create a new
|
||||
/// list of explicit supertrait bounds to render nicely.
|
||||
fn separate_supertrait_bounds(
|
||||
mut g: clean::Generics,
|
||||
) -> (clean::Generics, Vec<clean::GenericBound>) {
|
||||
fn separate_self_bounds(mut g: clean::Generics) -> (clean::Generics, Vec<clean::GenericBound>) {
|
||||
let mut ty_bounds = Vec::new();
|
||||
g.where_predicates.retain(|pred| match *pred {
|
||||
clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref bounds, .. } => {
|
||||
|
@ -806,22 +812,17 @@ fn separate_supertrait_bounds(
|
|||
}
|
||||
|
||||
pub(crate) fn record_extern_trait(cx: &mut DocContext<'_>, did: DefId) {
|
||||
if did.is_local() {
|
||||
if did.is_local()
|
||||
|| cx.external_traits.contains_key(&did)
|
||||
|| cx.active_extern_traits.contains(&did)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
if cx.external_traits.contains_key(&did) || cx.active_extern_traits.contains(&did) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
cx.active_extern_traits.insert(did);
|
||||
}
|
||||
cx.active_extern_traits.insert(did);
|
||||
|
||||
debug!("record_extern_trait: {did:?}");
|
||||
let trait_ = build_external_trait(cx, did);
|
||||
let trait_ = build_trait(cx, did);
|
||||
|
||||
cx.external_traits.insert(did, trait_);
|
||||
cx.active_extern_traits.remove(&did);
|
||||
|
|
|
@ -27,7 +27,7 @@ use rustc_span::source_map;
|
|||
use rustc_span::symbol::sym;
|
||||
use tracing::{debug, info};
|
||||
|
||||
use crate::clean::inline::build_external_trait;
|
||||
use crate::clean::inline::build_trait;
|
||||
use crate::clean::{self, ItemId};
|
||||
use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions};
|
||||
use crate::formats::cache::Cache;
|
||||
|
@ -385,7 +385,7 @@ pub(crate) fn run_global_ctxt(
|
|||
//
|
||||
// Note that in case of `#![no_core]`, the trait is not available.
|
||||
if let Some(sized_trait_did) = ctxt.tcx.lang_items().sized_trait() {
|
||||
let sized_trait = build_external_trait(&mut ctxt, sized_trait_did);
|
||||
let sized_trait = build_trait(&mut ctxt, sized_trait_did);
|
||||
ctxt.external_traits.insert(sized_trait_did, sized_trait);
|
||||
}
|
||||
|
||||
|
|
|
@ -1232,12 +1232,13 @@ fn item_trait_alias(
|
|||
wrap_item(w, |w| {
|
||||
write!(
|
||||
w,
|
||||
"{attrs}trait {name}{generics}{where_b} = {bounds};",
|
||||
"{attrs}trait {name}{generics} = {bounds}{where_clause};",
|
||||
attrs = render_attributes_in_pre(it, "", cx),
|
||||
name = it.name.unwrap(),
|
||||
generics = t.generics.print(cx),
|
||||
where_b = print_where_clause(&t.generics, cx, 0, Ending::Newline).maybe_display(),
|
||||
bounds = bounds(&t.bounds, true, cx),
|
||||
where_clause =
|
||||
print_where_clause(&t.generics, cx, 0, Ending::NoNewline).maybe_display(),
|
||||
)
|
||||
})?;
|
||||
|
||||
|
|
13
tests/rustdoc/auxiliary/ext-trait-aliases.rs
Normal file
13
tests/rustdoc/auxiliary/ext-trait-aliases.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
#![feature(trait_alias)]
|
||||
|
||||
pub trait ExtAlias0 = Copy + Iterator<Item = u8>;
|
||||
|
||||
pub trait ExtAlias1<'a, T: 'a + Clone, const N: usize> = From<[&'a T; N]>;
|
||||
|
||||
pub trait ExtAlias2<T> = where T: From<String>, String: Into<T>;
|
||||
|
||||
pub trait ExtAlias3 = Sized;
|
||||
|
||||
pub trait ExtAlias4 = where Self: Sized;
|
||||
|
||||
pub trait ExtAlias5 = ;
|
|
@ -1,3 +0,0 @@
|
|||
#![feature(trait_alias)]
|
||||
|
||||
pub trait SomeAlias = std::fmt::Debug + std::marker::Copy;
|
|
@ -1,10 +0,0 @@
|
|||
//@ aux-build:trait-alias-mention.rs
|
||||
//@ build-aux-docs
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
extern crate trait_alias_mention;
|
||||
|
||||
//@ has foo/fn.mention_alias_in_bounds.html '//a[@href="../trait_alias_mention/traitalias.SomeAlias.html"]' 'SomeAlias'
|
||||
pub fn mention_alias_in_bounds<T: trait_alias_mention::SomeAlias>() {
|
||||
}
|
82
tests/rustdoc/trait-aliases.rs
Normal file
82
tests/rustdoc/trait-aliases.rs
Normal file
|
@ -0,0 +1,82 @@
|
|||
// Basic testing for trait aliases.
|
||||
#![feature(trait_alias)]
|
||||
#![crate_name = "it"]
|
||||
|
||||
// Check the "local case" (HIR cleaning) //
|
||||
|
||||
//@ has it/all.html '//a[@href="traitalias.Alias0.html"]' 'Alias0'
|
||||
//@ has it/index.html '//h2[@id="trait-aliases"]' 'Trait Aliases'
|
||||
//@ has it/index.html '//a[@class="traitalias"]' 'Alias0'
|
||||
//@ has it/traitalias.Alias0.html
|
||||
//@ has - '//*[@class="rust item-decl"]//code' 'trait Alias0 = Copy + Iterator<Item = u8>;'
|
||||
pub trait Alias0 = Copy + Iterator<Item = u8>;
|
||||
|
||||
//@ has it/traitalias.Alias1.html
|
||||
//@ has - '//pre[@class="rust item-decl"]' \
|
||||
// "trait Alias1<'a, T: 'a + Clone, const N: usize> = From<[&'a T; N]>;"
|
||||
pub trait Alias1<'a, T: 'a + Clone, const N: usize> = From<[&'a T; N]>;
|
||||
|
||||
//@ has it/traitalias.Alias2.html
|
||||
//@ has - '//pre[@class="rust item-decl"]' \
|
||||
// 'trait Alias2<T> = where T: From<String>, String: Into<T>;'
|
||||
pub trait Alias2<T> = where T: From<String>, String: Into<T>;
|
||||
|
||||
//@ has it/traitalias.Alias3.html
|
||||
//@ has - '//pre[@class="rust item-decl"]' 'trait Alias3 = ;'
|
||||
pub trait Alias3 =;
|
||||
|
||||
//@ has it/traitalias.Alias4.html
|
||||
//@ has - '//pre[@class="rust item-decl"]' 'trait Alias4 = ;'
|
||||
pub trait Alias4 = where;
|
||||
|
||||
//@ has it/fn.usage0.html
|
||||
//@ has - '//pre[@class="rust item-decl"]' "pub fn usage0(_: impl Alias0)"
|
||||
//@ has - '//a[@href="traitalias.Alias0.html"]' 'Alias0'
|
||||
pub fn usage0(_: impl Alias0) {}
|
||||
|
||||
// FIXME: One can only "disambiguate" intra-doc links to trait aliases with `type@` but not with
|
||||
// `trait@` (fails to resolve) or `traitalias@` (doesn't exist). We should make at least one of
|
||||
// the latter two work, right?
|
||||
|
||||
//@ has it/link0/index.html
|
||||
//@ has - '//a/@href' 'traitalias.Alias0.html'
|
||||
//@ has - '//a/@href' 'traitalias.Alias1.html'
|
||||
/// [Alias0], [type@Alias1]
|
||||
pub mod link0 {}
|
||||
|
||||
// Check the "extern case" (middle cleaning) //
|
||||
|
||||
//@ aux-build: ext-trait-aliases.rs
|
||||
extern crate ext_trait_aliases as ext;
|
||||
|
||||
//@ has it/traitalias.ExtAlias0.html
|
||||
//@ has - '//pre[@class="rust item-decl"]' 'trait ExtAlias0 = Copy + Iterator<Item = u8>;'
|
||||
pub use ext::ExtAlias0;
|
||||
|
||||
//@ has it/traitalias.ExtAlias1.html
|
||||
//@ has - '//pre[@class="rust item-decl"]' \
|
||||
// "trait ExtAlias1<'a, T, const N: usize> = From<[&'a T; N]> where T: 'a + Clone;"
|
||||
pub use ext::ExtAlias1;
|
||||
|
||||
//@ has it/traitalias.ExtAlias2.html
|
||||
//@ has - '//pre[@class="rust item-decl"]' \
|
||||
// 'trait ExtAlias2<T> = where T: From<String>, String: Into<T>;'
|
||||
pub use ext::ExtAlias2;
|
||||
|
||||
//@ has it/traitalias.ExtAlias3.html
|
||||
//@ has - '//pre[@class="rust item-decl"]' 'trait ExtAlias3 = Sized;'
|
||||
pub use ext::ExtAlias3;
|
||||
|
||||
// NOTE: Middle cleaning can't discern `= Sized` and `= where Self: Sized` and that's okay.
|
||||
//@ has it/traitalias.ExtAlias4.html
|
||||
//@ has - '//pre[@class="rust item-decl"]' 'trait ExtAlias4 = Sized;'
|
||||
pub use ext::ExtAlias4;
|
||||
|
||||
//@ has it/traitalias.ExtAlias5.html
|
||||
//@ has - '//pre[@class="rust item-decl"]' 'trait ExtAlias5 = ;'
|
||||
pub use ext::ExtAlias5;
|
||||
|
||||
//@ has it/fn.usage1.html
|
||||
//@ has - '//pre[@class="rust item-decl"]' "pub fn usage1(_: impl ExtAlias0)"
|
||||
//@ has - '//a[@href="traitalias.ExtAlias0.html"]' 'ExtAlias0'
|
||||
pub fn usage1(_: impl ExtAlias0) {}
|
|
@ -1,26 +0,0 @@
|
|||
#![feature(trait_alias)]
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
//@ has foo/all.html '//a[@href="traitalias.CopyAlias.html"]' 'CopyAlias'
|
||||
//@ has foo/all.html '//a[@href="traitalias.Alias2.html"]' 'Alias2'
|
||||
//@ has foo/all.html '//a[@href="traitalias.Foo.html"]' 'Foo'
|
||||
|
||||
//@ has foo/index.html '//h2[@id="trait-aliases"]' 'Trait Aliases'
|
||||
//@ has foo/index.html '//a[@class="traitalias"]' 'CopyAlias'
|
||||
//@ has foo/index.html '//a[@class="traitalias"]' 'Alias2'
|
||||
//@ has foo/index.html '//a[@class="traitalias"]' 'Foo'
|
||||
|
||||
//@ has foo/traitalias.CopyAlias.html
|
||||
//@ has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait CopyAlias = Copy;'
|
||||
pub trait CopyAlias = Copy;
|
||||
//@ has foo/traitalias.Alias2.html
|
||||
//@ has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait Alias2 = Copy + Debug;'
|
||||
pub trait Alias2 = Copy + Debug;
|
||||
//@ has foo/traitalias.Foo.html
|
||||
//@ has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait Foo<T> = Into<T> + Debug;'
|
||||
pub trait Foo<T> = Into<T> + Debug;
|
||||
//@ has foo/fn.bar.html '//a[@href="traitalias.Alias2.html"]' 'Alias2'
|
||||
pub fn bar<T>() where T: Alias2 {}
|
Loading…
Add table
Add a link
Reference in a new issue