Skip to content

Commit aa26e1a

Browse files
authored
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.
2 parents ae21236 + 6df0ccf commit aa26e1a

File tree

4 files changed

+122
-55
lines changed

4 files changed

+122
-55
lines changed

compiler/rustc_passes/src/check_attr.rs

+10
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
952952
bare_fn_ty.decl.inputs.len() == 1
953953
} else {
954954
false
955+
}
956+
|| if let Some(&[hir::GenericArg::Type(ty)]) = i
957+
.of_trait
958+
.as_ref()
959+
.and_then(|trait_ref| trait_ref.path.segments.last())
960+
.map(|last_segment| last_segment.args().args)
961+
{
962+
matches!(&ty.kind, hir::TyKind::Tup([_]))
963+
} else {
964+
false
955965
};
956966
if !is_valid {
957967
self.dcx().emit_err(errors::DocFakeVariadicNotValid { span: meta.span() });

library/core/src/tuple.rs

+21-15
Original file line numberDiff line numberDiff line change
@@ -122,23 +122,29 @@ macro_rules! tuple_impls {
122122
}
123123
}
124124

125-
#[stable(feature = "array_tuple_conv", since = "1.71.0")]
126-
impl<T> From<[T; ${count($T)}]> for ($(${ignore($T)} T,)+) {
127-
#[inline]
128-
#[allow(non_snake_case)]
129-
fn from(array: [T; ${count($T)}]) -> Self {
130-
let [$($T,)+] = array;
131-
($($T,)+)
125+
maybe_tuple_doc! {
126+
$($T)+ @
127+
#[stable(feature = "array_tuple_conv", since = "1.71.0")]
128+
impl<T> From<[T; ${count($T)}]> for ($(${ignore($T)} T,)+) {
129+
#[inline]
130+
#[allow(non_snake_case)]
131+
fn from(array: [T; ${count($T)}]) -> Self {
132+
let [$($T,)+] = array;
133+
($($T,)+)
134+
}
132135
}
133136
}
134137

135-
#[stable(feature = "array_tuple_conv", since = "1.71.0")]
136-
impl<T> From<($(${ignore($T)} T,)+)> for [T; ${count($T)}] {
137-
#[inline]
138-
#[allow(non_snake_case)]
139-
fn from(tuple: ($(${ignore($T)} T,)+)) -> Self {
140-
let ($($T,)+) = tuple;
141-
[$($T,)+]
138+
maybe_tuple_doc! {
139+
$($T)+ @
140+
#[stable(feature = "array_tuple_conv", since = "1.71.0")]
141+
impl<T> From<($(${ignore($T)} T,)+)> for [T; ${count($T)}] {
142+
#[inline]
143+
#[allow(non_snake_case)]
144+
fn from(tuple: ($(${ignore($T)} T,)+)) -> Self {
145+
let ($($T,)+) = tuple;
146+
[$($T,)+]
147+
}
142148
}
143149
}
144150
}
@@ -148,7 +154,7 @@ macro_rules! tuple_impls {
148154
// Otherwise, it hides the docs entirely.
149155
macro_rules! maybe_tuple_doc {
150156
($a:ident @ #[$meta:meta] $item:item) => {
151-
#[doc(fake_variadic)]
157+
#[cfg_attr(not(bootstrap), doc(fake_variadic))]
152158
#[doc = "This trait is implemented for tuples up to twelve items long."]
153159
#[$meta]
154160
$item

src/librustdoc/html/format.rs

+74-40
Original file line numberDiff line numberDiff line change
@@ -1288,56 +1288,90 @@ impl clean::Impl {
12881288
if self.is_negative_trait_impl() {
12891289
write!(f, "!")?;
12901290
}
1291-
ty.print(cx).fmt(f)?;
1291+
if self.kind.is_fake_variadic()
1292+
&& let generics = ty.generics()
1293+
&& let &[inner_type] = generics.as_ref().map_or(&[][..], |v| &v[..])
1294+
{
1295+
let last = ty.last();
1296+
if f.alternate() {
1297+
write!(f, "{}<", last)?;
1298+
self.print_type(inner_type, f, use_absolute, cx)?;
1299+
write!(f, ">")?;
1300+
} else {
1301+
write!(f, "{}&lt;", anchor(ty.def_id(), last, cx).to_string())?;
1302+
self.print_type(inner_type, f, use_absolute, cx)?;
1303+
write!(f, "&gt;")?;
1304+
}
1305+
} else {
1306+
ty.print(cx).fmt(f)?;
1307+
}
12921308
write!(f, " for ")?;
12931309
}
12941310

1295-
if let clean::Type::Tuple(types) = &self.for_
1296-
&& let [clean::Type::Generic(name)] = &types[..]
1297-
&& (self.kind.is_fake_variadic() || self.kind.is_auto())
1298-
{
1299-
// Hardcoded anchor library/core/src/primitive_docs.rs
1300-
// Link should match `# Trait implementations`
1301-
primitive_link_fragment(
1302-
f,
1303-
PrimitiveType::Tuple,
1304-
format_args!("({name}₁, {name}₂, …, {name}ₙ)"),
1305-
"#trait-implementations-1",
1306-
cx,
1307-
)?;
1308-
} else if let clean::BareFunction(bare_fn) = &self.for_
1309-
&& let [clean::Argument { type_: clean::Type::Generic(name), .. }] =
1310-
&bare_fn.decl.inputs.values[..]
1311-
&& (self.kind.is_fake_variadic() || self.kind.is_auto())
1312-
{
1313-
// Hardcoded anchor library/core/src/primitive_docs.rs
1314-
// Link should match `# Trait implementations`
1315-
1316-
print_higher_ranked_params_with_space(&bare_fn.generic_params, cx).fmt(f)?;
1317-
bare_fn.safety.print_with_space().fmt(f)?;
1318-
print_abi_with_space(bare_fn.abi).fmt(f)?;
1319-
let ellipsis = if bare_fn.decl.c_variadic { ", ..." } else { "" };
1320-
primitive_link_fragment(
1321-
f,
1322-
PrimitiveType::Tuple,
1323-
format_args!("fn({name}₁, {name}₂, …, {name}ₙ{ellipsis})"),
1324-
"#trait-implementations-1",
1325-
cx,
1326-
)?;
1327-
// Write output.
1328-
if !bare_fn.decl.output.is_unit() {
1329-
write!(f, " -> ")?;
1330-
fmt_type(&bare_fn.decl.output, f, use_absolute, cx)?;
1331-
}
1332-
} else if let Some(ty) = self.kind.as_blanket_ty() {
1311+
if let Some(ty) = self.kind.as_blanket_ty() {
13331312
fmt_type(ty, f, use_absolute, cx)?;
13341313
} else {
1335-
fmt_type(&self.for_, f, use_absolute, cx)?;
1314+
self.print_type(&self.for_, f, use_absolute, cx)?;
13361315
}
13371316

13381317
print_where_clause(&self.generics, cx, 0, Ending::Newline).fmt(f)
13391318
})
13401319
}
1320+
fn print_type<'a, 'tcx: 'a>(
1321+
&self,
1322+
type_: &clean::Type,
1323+
f: &mut fmt::Formatter<'_>,
1324+
use_absolute: bool,
1325+
cx: &'a Context<'tcx>,
1326+
) -> Result<(), fmt::Error> {
1327+
if let clean::Type::Tuple(types) = type_
1328+
&& let [clean::Type::Generic(name)] = &types[..]
1329+
&& (self.kind.is_fake_variadic() || self.kind.is_auto())
1330+
{
1331+
// Hardcoded anchor library/core/src/primitive_docs.rs
1332+
// Link should match `# Trait implementations`
1333+
primitive_link_fragment(
1334+
f,
1335+
PrimitiveType::Tuple,
1336+
format_args!("({name}₁, {name}₂, …, {name}ₙ)"),
1337+
"#trait-implementations-1",
1338+
cx,
1339+
)?;
1340+
} else if let clean::Type::Array(ty, len) = type_
1341+
&& let clean::Type::Generic(name) = &**ty
1342+
&& &len[..] == "1"
1343+
&& (self.kind.is_fake_variadic() || self.kind.is_auto())
1344+
{
1345+
primitive_link(f, PrimitiveType::Array, format_args!("[{name}; N]"), cx)?;
1346+
} else if let clean::BareFunction(bare_fn) = &type_
1347+
&& let [clean::Argument { type_: clean::Type::Generic(name), .. }] =
1348+
&bare_fn.decl.inputs.values[..]
1349+
&& (self.kind.is_fake_variadic() || self.kind.is_auto())
1350+
{
1351+
// Hardcoded anchor library/core/src/primitive_docs.rs
1352+
// Link should match `# Trait implementations`
1353+
1354+
print_higher_ranked_params_with_space(&bare_fn.generic_params, cx).fmt(f)?;
1355+
bare_fn.safety.print_with_space().fmt(f)?;
1356+
print_abi_with_space(bare_fn.abi).fmt(f)?;
1357+
let ellipsis = if bare_fn.decl.c_variadic { ", ..." } else { "" };
1358+
primitive_link_fragment(
1359+
f,
1360+
PrimitiveType::Tuple,
1361+
format_args!("fn({name}₁, {name}₂, …, {name}ₙ{ellipsis})"),
1362+
"#trait-implementations-1",
1363+
cx,
1364+
)?;
1365+
// Write output.
1366+
if !bare_fn.decl.output.is_unit() {
1367+
write!(f, " -> ")?;
1368+
fmt_type(&bare_fn.decl.output, f, use_absolute, cx)?;
1369+
}
1370+
} else {
1371+
fmt_type(&type_, f, use_absolute, cx)?;
1372+
}
1373+
Ok(())
1374+
}
13411375
}
13421376

13431377
impl clean::Arguments {

tests/rustdoc/primitive-tuple-variadic.rs

+17
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,20 @@ pub trait Bar {}
1616
//@ has - '//section[@id="impl-Bar-for-(U,)"]/h3' 'impl<U: Foo> Bar for (U₁, U₂, …, Uₙ)'
1717
#[doc(fake_variadic)]
1818
impl<U: Foo> Bar for (U,) {}
19+
20+
pub trait Baz<T> { fn baz(&self) -> T { todo!() } }
21+
22+
//@ has foo/trait.Baz.html
23+
//@ has - '//section[@id="impl-Baz%3C(T,)%3E-for-%5BT;+1%5D"]/h3' 'impl<T> Baz<(T₁, T₂, …, Tₙ)> for [T; N]'
24+
#[doc(fake_variadic)]
25+
impl<T> Baz<(T,)> for [T; 1] {}
26+
27+
//@ has foo/trait.Baz.html
28+
//@ has - '//section[@id="impl-Baz%3C%5BT;+1%5D%3E-for-(T,)"]/h3' 'impl<T> Baz<[T; N]> for (T₁, T₂, …, Tₙ)'
29+
#[doc(fake_variadic)]
30+
impl<T> Baz<[T; 1]> for (T,) {}
31+
32+
//@ has foo/trait.Baz.html
33+
//@ has - '//section[@id="impl-Baz%3CT%3E-for-(T,)"]/h3' 'impl<T> Baz<T> for (T₁, T₂, …, Tₙ)'
34+
#[doc(fake_variadic)]
35+
impl<T> Baz<T> for (T,) {}

0 commit comments

Comments
 (0)