Rollup merge of #129525 - notriddle:notriddle/fake-variadic-tuple-array, r=GuillaumeGomez
rustdoc: clean up tuple <-> primitive conversion docs This adds a minor missing feature to `fake_variadic`, so that it can render `impl From<(T,)> for [T; 1]` correctly.
This commit is contained in:
commit
aa26e1ad97
@ -952,6 +952,16 @@ fn check_doc_fake_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) {
|
|||||||
bare_fn_ty.decl.inputs.len() == 1
|
bare_fn_ty.decl.inputs.len() == 1
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
}
|
||||||
|
|| if let Some(&[hir::GenericArg::Type(ty)]) = i
|
||||||
|
.of_trait
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|trait_ref| trait_ref.path.segments.last())
|
||||||
|
.map(|last_segment| last_segment.args().args)
|
||||||
|
{
|
||||||
|
matches!(&ty.kind, hir::TyKind::Tup([_]))
|
||||||
|
} else {
|
||||||
|
false
|
||||||
};
|
};
|
||||||
if !is_valid {
|
if !is_valid {
|
||||||
self.dcx().emit_err(errors::DocFakeVariadicNotValid { span: meta.span() });
|
self.dcx().emit_err(errors::DocFakeVariadicNotValid { span: meta.span() });
|
||||||
|
@ -122,23 +122,29 @@ fn default() -> ($($T,)+) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "array_tuple_conv", since = "1.71.0")]
|
maybe_tuple_doc! {
|
||||||
impl<T> From<[T; ${count($T)}]> for ($(${ignore($T)} T,)+) {
|
$($T)+ @
|
||||||
#[inline]
|
#[stable(feature = "array_tuple_conv", since = "1.71.0")]
|
||||||
#[allow(non_snake_case)]
|
impl<T> From<[T; ${count($T)}]> for ($(${ignore($T)} T,)+) {
|
||||||
fn from(array: [T; ${count($T)}]) -> Self {
|
#[inline]
|
||||||
let [$($T,)+] = array;
|
#[allow(non_snake_case)]
|
||||||
($($T,)+)
|
fn from(array: [T; ${count($T)}]) -> Self {
|
||||||
|
let [$($T,)+] = array;
|
||||||
|
($($T,)+)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "array_tuple_conv", since = "1.71.0")]
|
maybe_tuple_doc! {
|
||||||
impl<T> From<($(${ignore($T)} T,)+)> for [T; ${count($T)}] {
|
$($T)+ @
|
||||||
#[inline]
|
#[stable(feature = "array_tuple_conv", since = "1.71.0")]
|
||||||
#[allow(non_snake_case)]
|
impl<T> From<($(${ignore($T)} T,)+)> for [T; ${count($T)}] {
|
||||||
fn from(tuple: ($(${ignore($T)} T,)+)) -> Self {
|
#[inline]
|
||||||
let ($($T,)+) = tuple;
|
#[allow(non_snake_case)]
|
||||||
[$($T,)+]
|
fn from(tuple: ($(${ignore($T)} T,)+)) -> Self {
|
||||||
|
let ($($T,)+) = tuple;
|
||||||
|
[$($T,)+]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,7 +154,7 @@ fn from(tuple: ($(${ignore($T)} T,)+)) -> Self {
|
|||||||
// Otherwise, it hides the docs entirely.
|
// Otherwise, it hides the docs entirely.
|
||||||
macro_rules! maybe_tuple_doc {
|
macro_rules! maybe_tuple_doc {
|
||||||
($a:ident @ #[$meta:meta] $item:item) => {
|
($a:ident @ #[$meta:meta] $item:item) => {
|
||||||
#[doc(fake_variadic)]
|
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
|
||||||
#[doc = "This trait is implemented for tuples up to twelve items long."]
|
#[doc = "This trait is implemented for tuples up to twelve items long."]
|
||||||
#[$meta]
|
#[$meta]
|
||||||
$item
|
$item
|
||||||
|
@ -1288,56 +1288,90 @@ pub(crate) fn print<'a, 'tcx: 'a>(
|
|||||||
if self.is_negative_trait_impl() {
|
if self.is_negative_trait_impl() {
|
||||||
write!(f, "!")?;
|
write!(f, "!")?;
|
||||||
}
|
}
|
||||||
ty.print(cx).fmt(f)?;
|
if self.kind.is_fake_variadic()
|
||||||
|
&& let generics = ty.generics()
|
||||||
|
&& let &[inner_type] = generics.as_ref().map_or(&[][..], |v| &v[..])
|
||||||
|
{
|
||||||
|
let last = ty.last();
|
||||||
|
if f.alternate() {
|
||||||
|
write!(f, "{}<", last)?;
|
||||||
|
self.print_type(inner_type, f, use_absolute, cx)?;
|
||||||
|
write!(f, ">")?;
|
||||||
|
} else {
|
||||||
|
write!(f, "{}<", anchor(ty.def_id(), last, cx).to_string())?;
|
||||||
|
self.print_type(inner_type, f, use_absolute, cx)?;
|
||||||
|
write!(f, ">")?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ty.print(cx).fmt(f)?;
|
||||||
|
}
|
||||||
write!(f, " for ")?;
|
write!(f, " for ")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let clean::Type::Tuple(types) = &self.for_
|
if let Some(ty) = self.kind.as_blanket_ty() {
|
||||||
&& let [clean::Type::Generic(name)] = &types[..]
|
|
||||||
&& (self.kind.is_fake_variadic() || self.kind.is_auto())
|
|
||||||
{
|
|
||||||
// Hardcoded anchor library/core/src/primitive_docs.rs
|
|
||||||
// Link should match `# Trait implementations`
|
|
||||||
primitive_link_fragment(
|
|
||||||
f,
|
|
||||||
PrimitiveType::Tuple,
|
|
||||||
format_args!("({name}₁, {name}₂, …, {name}ₙ)"),
|
|
||||||
"#trait-implementations-1",
|
|
||||||
cx,
|
|
||||||
)?;
|
|
||||||
} else if let clean::BareFunction(bare_fn) = &self.for_
|
|
||||||
&& let [clean::Argument { type_: clean::Type::Generic(name), .. }] =
|
|
||||||
&bare_fn.decl.inputs.values[..]
|
|
||||||
&& (self.kind.is_fake_variadic() || self.kind.is_auto())
|
|
||||||
{
|
|
||||||
// Hardcoded anchor library/core/src/primitive_docs.rs
|
|
||||||
// Link should match `# Trait implementations`
|
|
||||||
|
|
||||||
print_higher_ranked_params_with_space(&bare_fn.generic_params, cx).fmt(f)?;
|
|
||||||
bare_fn.safety.print_with_space().fmt(f)?;
|
|
||||||
print_abi_with_space(bare_fn.abi).fmt(f)?;
|
|
||||||
let ellipsis = if bare_fn.decl.c_variadic { ", ..." } else { "" };
|
|
||||||
primitive_link_fragment(
|
|
||||||
f,
|
|
||||||
PrimitiveType::Tuple,
|
|
||||||
format_args!("fn({name}₁, {name}₂, …, {name}ₙ{ellipsis})"),
|
|
||||||
"#trait-implementations-1",
|
|
||||||
cx,
|
|
||||||
)?;
|
|
||||||
// Write output.
|
|
||||||
if !bare_fn.decl.output.is_unit() {
|
|
||||||
write!(f, " -> ")?;
|
|
||||||
fmt_type(&bare_fn.decl.output, f, use_absolute, cx)?;
|
|
||||||
}
|
|
||||||
} else if let Some(ty) = self.kind.as_blanket_ty() {
|
|
||||||
fmt_type(ty, f, use_absolute, cx)?;
|
fmt_type(ty, f, use_absolute, cx)?;
|
||||||
} else {
|
} else {
|
||||||
fmt_type(&self.for_, f, use_absolute, cx)?;
|
self.print_type(&self.for_, f, use_absolute, cx)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
print_where_clause(&self.generics, cx, 0, Ending::Newline).fmt(f)
|
print_where_clause(&self.generics, cx, 0, Ending::Newline).fmt(f)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
fn print_type<'a, 'tcx: 'a>(
|
||||||
|
&self,
|
||||||
|
type_: &clean::Type,
|
||||||
|
f: &mut fmt::Formatter<'_>,
|
||||||
|
use_absolute: bool,
|
||||||
|
cx: &'a Context<'tcx>,
|
||||||
|
) -> Result<(), fmt::Error> {
|
||||||
|
if let clean::Type::Tuple(types) = type_
|
||||||
|
&& let [clean::Type::Generic(name)] = &types[..]
|
||||||
|
&& (self.kind.is_fake_variadic() || self.kind.is_auto())
|
||||||
|
{
|
||||||
|
// Hardcoded anchor library/core/src/primitive_docs.rs
|
||||||
|
// Link should match `# Trait implementations`
|
||||||
|
primitive_link_fragment(
|
||||||
|
f,
|
||||||
|
PrimitiveType::Tuple,
|
||||||
|
format_args!("({name}₁, {name}₂, …, {name}ₙ)"),
|
||||||
|
"#trait-implementations-1",
|
||||||
|
cx,
|
||||||
|
)?;
|
||||||
|
} else if let clean::Type::Array(ty, len) = type_
|
||||||
|
&& let clean::Type::Generic(name) = &**ty
|
||||||
|
&& &len[..] == "1"
|
||||||
|
&& (self.kind.is_fake_variadic() || self.kind.is_auto())
|
||||||
|
{
|
||||||
|
primitive_link(f, PrimitiveType::Array, format_args!("[{name}; N]"), cx)?;
|
||||||
|
} else if let clean::BareFunction(bare_fn) = &type_
|
||||||
|
&& let [clean::Argument { type_: clean::Type::Generic(name), .. }] =
|
||||||
|
&bare_fn.decl.inputs.values[..]
|
||||||
|
&& (self.kind.is_fake_variadic() || self.kind.is_auto())
|
||||||
|
{
|
||||||
|
// Hardcoded anchor library/core/src/primitive_docs.rs
|
||||||
|
// Link should match `# Trait implementations`
|
||||||
|
|
||||||
|
print_higher_ranked_params_with_space(&bare_fn.generic_params, cx).fmt(f)?;
|
||||||
|
bare_fn.safety.print_with_space().fmt(f)?;
|
||||||
|
print_abi_with_space(bare_fn.abi).fmt(f)?;
|
||||||
|
let ellipsis = if bare_fn.decl.c_variadic { ", ..." } else { "" };
|
||||||
|
primitive_link_fragment(
|
||||||
|
f,
|
||||||
|
PrimitiveType::Tuple,
|
||||||
|
format_args!("fn({name}₁, {name}₂, …, {name}ₙ{ellipsis})"),
|
||||||
|
"#trait-implementations-1",
|
||||||
|
cx,
|
||||||
|
)?;
|
||||||
|
// Write output.
|
||||||
|
if !bare_fn.decl.output.is_unit() {
|
||||||
|
write!(f, " -> ")?;
|
||||||
|
fmt_type(&bare_fn.decl.output, f, use_absolute, cx)?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt_type(&type_, f, use_absolute, cx)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl clean::Arguments {
|
impl clean::Arguments {
|
||||||
|
@ -16,3 +16,20 @@ pub trait Bar {}
|
|||||||
//@ has - '//section[@id="impl-Bar-for-(U,)"]/h3' 'impl<U: Foo> Bar for (U₁, U₂, …, Uₙ)'
|
//@ has - '//section[@id="impl-Bar-for-(U,)"]/h3' 'impl<U: Foo> Bar for (U₁, U₂, …, Uₙ)'
|
||||||
#[doc(fake_variadic)]
|
#[doc(fake_variadic)]
|
||||||
impl<U: Foo> Bar for (U,) {}
|
impl<U: Foo> Bar for (U,) {}
|
||||||
|
|
||||||
|
pub trait Baz<T> { fn baz(&self) -> T { todo!() } }
|
||||||
|
|
||||||
|
//@ has foo/trait.Baz.html
|
||||||
|
//@ has - '//section[@id="impl-Baz%3C(T,)%3E-for-%5BT;+1%5D"]/h3' 'impl<T> Baz<(T₁, T₂, …, Tₙ)> for [T; N]'
|
||||||
|
#[doc(fake_variadic)]
|
||||||
|
impl<T> Baz<(T,)> for [T; 1] {}
|
||||||
|
|
||||||
|
//@ has foo/trait.Baz.html
|
||||||
|
//@ has - '//section[@id="impl-Baz%3C%5BT;+1%5D%3E-for-(T,)"]/h3' 'impl<T> Baz<[T; N]> for (T₁, T₂, …, Tₙ)'
|
||||||
|
#[doc(fake_variadic)]
|
||||||
|
impl<T> Baz<[T; 1]> for (T,) {}
|
||||||
|
|
||||||
|
//@ has foo/trait.Baz.html
|
||||||
|
//@ has - '//section[@id="impl-Baz%3CT%3E-for-(T,)"]/h3' 'impl<T> Baz<T> for (T₁, T₂, …, Tₙ)'
|
||||||
|
#[doc(fake_variadic)]
|
||||||
|
impl<T> Baz<T> for (T,) {}
|
||||||
|
Loading…
Reference in New Issue
Block a user