Skip to content

Unify generation of primitive links for associated types with the rest #114096

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 51 additions & 66 deletions src/librustdoc/html/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,24 @@ pub(crate) fn anchor<'a, 'cx: 'a>(
})
}

fn fmt_slice<'cx>(
f: &mut fmt::Formatter<'_>,
t: &clean::Type,
extra: &str,
cx: &'cx Context<'_>,
) -> fmt::Result {
match *t {
clean::Generic(name) => {
primitive_link(f, PrimitiveType::Slice, &format!("{extra}[{name}]"), cx)
}
_ => {
write!(f, "{extra}[")?;
fmt::Display::fmt(&t.print(cx), f)?;
f.write_str("]")
}
}
}

fn fmt_type<'cx>(
t: &clean::Type,
f: &mut fmt::Formatter<'_>,
Expand Down Expand Up @@ -1008,55 +1026,25 @@ fn fmt_type<'cx>(
match &typs[..] {
&[] => primitive_link(f, PrimitiveType::Unit, "()", cx),
[one] => {
if let clean::Generic(name) = one {
primitive_link(f, PrimitiveType::Tuple, &format!("({name},)"), cx)
} else {
write!(f, "(")?;
// Carry `f.alternate()` into this display w/o branching manually.
fmt::Display::fmt(&one.print(cx), f)?;
write!(f, ",)")
}
write!(f, "(")?;
// Carry `f.alternate()` into this display w/o branching manually.
fmt::Display::fmt(&one.print(cx), f)?;
write!(f, ",)")
}
many => {
let generic_names: Vec<Symbol> = many
.iter()
.filter_map(|t| match t {
clean::Generic(name) => Some(*name),
_ => None,
})
.collect();
let is_generic = generic_names.len() == many.len();
if is_generic {
primitive_link(
f,
PrimitiveType::Tuple,
&format!("({})", generic_names.iter().map(|s| s.as_str()).join(", ")),
cx,
)
} else {
write!(f, "(")?;
for (i, item) in many.iter().enumerate() {
if i != 0 {
write!(f, ", ")?;
}
// Carry `f.alternate()` into this display w/o branching manually.
fmt::Display::fmt(&item.print(cx), f)?;
write!(f, "(")?;
for (i, item) in many.iter().enumerate() {
if i != 0 {
write!(f, ", ")?;
}
write!(f, ")")
// Carry `f.alternate()` into this display w/o branching manually.
fmt::Display::fmt(&item.print(cx), f)?;
}
write!(f, ")")
}
}
}
clean::Slice(ref t) => match **t {
clean::Generic(name) => {
primitive_link(f, PrimitiveType::Slice, &format!("[{name}]"), cx)
}
_ => {
write!(f, "[")?;
fmt::Display::fmt(&t.print(cx), f)?;
write!(f, "]")
}
},
clean::Slice(ref t) => fmt_slice(f, &**t, "", cx),
clean::Array(ref t, ref n) => match **t {
clean::Generic(name) if !f.alternate() => primitive_link(
f,
Expand All @@ -1070,10 +1058,9 @@ fn fmt_type<'cx>(
if f.alternate() {
write!(f, "; {n}")?;
} else {
write!(f, "; ")?;
primitive_link(f, PrimitiveType::Array, &format!("{n}", n = Escape(n)), cx)?;
write!(f, "; {}", Escape(n))?;
}
write!(f, "]")
f.write_str("]")
}
},
clean::RawPointer(m, ref t) => {
Expand All @@ -1082,36 +1069,34 @@ fn fmt_type<'cx>(
hir::Mutability::Not => "const",
};

if matches!(**t, clean::Generic(_)) || t.is_assoc_ty() {
let text = if f.alternate() {
format!("*{m} {ty:#}", ty = t.print(cx))
} else {
format!("*{m} {ty}", ty = t.print(cx))
};
primitive_link(f, clean::PrimitiveType::RawPointer, &text, cx)
} else {
primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{m} "), cx)?;
fmt::Display::fmt(&t.print(cx), f)
}
primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{m} "), cx)?;
fmt::Display::fmt(&t.print(cx), f)
}
clean::BorrowedRef { lifetime: ref l, mutability, type_: ref ty } => {
let lt = match l {
let lifetime = match l {
Some(l) => format!("{} ", l.print()),
_ => String::new(),
};
let m = mutability.print_with_space();
let amp = if f.alternate() { "&" } else { "&amp;" };

if let clean::Generic(name) = **ty {
return primitive_link(
f,
PrimitiveType::Reference,
&format!("{amp}{lt}{m}{name}"),
cx,
);
match **ty {
clean::Generic(name) => {
primitive_link(
f,
PrimitiveType::Reference,
&format!("{amp}{lifetime}{m}"),
cx,
)?;
return write!(f, "{name}");
}
clean::Slice(ref t) => {
return fmt_slice(f, &**t, &format!("{amp}{lifetime}{m}"), cx);
}
_ => {}
}

write!(f, "{amp}{lt}{m}")?;
write!(f, "{amp}{lifetime}{m}")?;

let needs_parens = match **ty {
clean::DynTrait(ref bounds, ref trait_lt)
Expand Down Expand Up @@ -1192,7 +1177,7 @@ fn fmt_type<'cx>(
write!(
f,
"<a class=\"associatedtype\" href=\"{url}#{shortty}.{name}\" \
title=\"type {path}::{name}\">{name}</a>",
title=\"type {path}::{name}\">{name}</a>",
shortty = ItemType::AssocType,
name = assoc.name,
path = join_with_double_colon(&path),
Expand Down
2 changes: 1 addition & 1 deletion tests/rustdoc/array-links.link_box_u32.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<code>pub fn gamma() -&gt; <a class="struct" href="struct.MyBox.html" title="struct foo::MyBox">MyBox</a>&lt;[<a class="primitive" href="{{channel}}/core/primitive.u32.html">u32</a>; <a class="primitive" href="{{channel}}/core/primitive.array.html">1</a>]&gt;</code>
<code>pub fn gamma() -&gt; <a class="struct" href="struct.MyBox.html" title="struct foo::MyBox">MyBox</a>&lt;[<a class="primitive" href="{{channel}}/core/primitive.u32.html">u32</a>; 1]&gt;</code>
2 changes: 1 addition & 1 deletion tests/rustdoc/array-links.link_slice_u32.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<code>pub fn alpha() -&gt; &amp;'static [<a class="primitive" href="{{channel}}/core/primitive.u32.html">u32</a>; <a class="primitive" href="{{channel}}/core/primitive.array.html">1</a>]</code>
<code>pub fn alpha() -&gt; &amp;'static [<a class="primitive" href="{{channel}}/core/primitive.u32.html">u32</a>; 1]</code>
2 changes: 1 addition & 1 deletion tests/rustdoc/issue-15318.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ extern crate issue_15318;

// @has issue_15318/fn.bar.html \
// '//*[@href="http://example.com/issue_15318/primitive.pointer.html"]' \
// '*mut T'
// '*mut '
pub fn bar<T>(ptr: *mut T) {}
64 changes: 64 additions & 0 deletions tests/rustdoc/primitive-links.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Test to ensure that `&` are handled the same way for generics and
// for other "normal" types.

#![crate_name = "foo"]

// @has 'foo/trait.Trait.html'

pub struct Struct;

pub trait Trait<Rhs = Self> {
// @count - '//*[@id="tymethod.method"]/*[@class="code-header"]/a' 2
// @has - '//*[@id="tymethod.method"]/*[@class="code-header"]/a' 'method'
// @has - '//*[@id="tymethod.method"]/*[@class="code-header"]/a' '&'
fn method(&self, other: &Rhs);
// @count - '//*[@id="tymethod.method2"]/*[@class="code-header"]/a' 2
// @has - '//*[@id="tymethod.method2"]/*[@class="code-header"]/a' 'method2'
// @has - '//*[@id="tymethod.method2"]/*[@class="code-header"]/a' '*const'
fn method2(&self, other: *const Rhs);
// There should be only one `<a>` (just the method).
// @count - '//*[@id="tymethod.bar"]/*[@class="code-header"]/a' 1
// @has - '//*[@id="tymethod.bar"]/*[@class="code-header"]/a' 'bar'
fn bar(&self, other: Rhs);
// There should be two `<a>` (method and `Struct`).
// @count - '//*[@id="tymethod.foo"]/*[@class="code-header"]/a' 2
// @has - '//*[@id="tymethod.foo"]/*[@class="code-header"]/a' 'foo'
// @has - '//*[@id="tymethod.foo"]/*[@class="code-header"]/a' 'Struct'
fn foo(&self, other: &Struct);
// There should be three `<a>` (method, `Struct` and `*const`).
// @count - '//*[@id="tymethod.foo2"]/*[@class="code-header"]/a' 3
// @has - '//*[@id="tymethod.foo2"]/*[@class="code-header"]/a' 'foo2'
// @has - '//*[@id="tymethod.foo2"]/*[@class="code-header"]/a' 'Struct'
// @has - '//*[@id="tymethod.foo2"]/*[@class="code-header"]/a' '*const'
fn foo2(&self, other: *const Struct);
// There should be only one `<a>` (just the method).
// @count - '//*[@id="tymethod.tuple"]/*[@class="code-header"]/a' 1
// @has - '//*[@id="tymethod.tuple"]/*[@class="code-header"]/a' 'tuple'
fn tuple(&self, other: (Rhs, Rhs));
// There should be two `<a>` (method and `Struct`).
// @count - '//*[@id="tymethod.tuple2"]/*[@class="code-header"]/a' 2
// @has - '//*[@id="tymethod.tuple2"]/*[@class="code-header"]/a' 'tuple2'
// @has - '//*[@id="tymethod.tuple2"]/*[@class="code-header"]/a' 'Struct'
fn tuple2(&self, other: (Struct, Rhs));
// @count - '//*[@id="tymethod.slice"]/*[@class="code-header"]/a' 2
// @has - '//*[@id="tymethod.slice"]/*[@class="code-header"]/a' 'slice'
// @has - '//*[@id="tymethod.slice"]/*[@class="code-header"]/a' '&[Rhs]'
fn slice(&self, other: &[Rhs]);
// @count - '//*[@id="tymethod.ref_array"]/*[@class="code-header"]/a' 2
// @has - '//*[@id="tymethod.ref_array"]/*[@class="code-header"]/a' 'ref_array'
// @has - '//*[@id="tymethod.ref_array"]/*[@class="code-header"]/a' '[Rhs; 2]'
fn ref_array(&self, other: &[Rhs; 2]);
// There should be two `<a>` (method and `Struct`).
// @count - '//*[@id="tymethod.slice2"]/*[@class="code-header"]/a' 2
// @has - '//*[@id="tymethod.slice2"]/*[@class="code-header"]/a' 'slice2'
// @has - '//*[@id="tymethod.slice2"]/*[@class="code-header"]/a' 'Struct'
fn slice2(&self, other: &[Struct]);
// @count - '//*[@id="tymethod.array"]/*[@class="code-header"]/a' 2
// @has - '//*[@id="tymethod.array"]/*[@class="code-header"]/a' 'array'
// @has - '//*[@id="tymethod.array"]/*[@class="code-header"]/a' '[Rhs; 2]'
fn array(&self, other: [Rhs; 2]);
// @count - '//*[@id="tymethod.array2"]/*[@class="code-header"]/a' 2
// @has - '//*[@id="tymethod.array2"]/*[@class="code-header"]/a' 'array2'
// @has - '//*[@id="tymethod.array2"]/*[@class="code-header"]/a' 'Struct'
fn array2(&self, other: [Struct; 2]);
}
2 changes: 1 addition & 1 deletion tests/rustdoc/slice-links.link_slice_generic.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<code>pub fn beta&lt;T&gt;() -&gt; &amp;'static <a class="primitive" href="{{channel}}/core/primitive.slice.html">[T]</a></code>
<code>pub fn beta&lt;T&gt;() -&gt; <a class="primitive" href="{{channel}}/core/primitive.slice.html">&amp;'static [T]</a></code>
2 changes: 1 addition & 1 deletion tests/rustdoc/tuples.link1_t.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<code>pub fn tuple1_t&lt;T&gt;(x: <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T,)</a>) -&gt; <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T,)</a></code>
<code>pub fn tuple1_t&lt;T&gt;(x: (T,)) -&gt; (T,)</code>
2 changes: 1 addition & 1 deletion tests/rustdoc/tuples.link2_t.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<code>pub fn tuple2_t&lt;T&gt;(x: <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T, T)</a>) -&gt; <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T, T)</a></code>
<code>pub fn tuple2_t&lt;T&gt;(x: (T, T)) -&gt; (T, T)</code>
2 changes: 1 addition & 1 deletion tests/rustdoc/tuples.link2_tu.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<code>pub fn tuple2_tu&lt;T, U&gt;(x: <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T, U)</a>) -&gt; <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T, U)</a></code>
<code>pub fn tuple2_tu&lt;T, U&gt;(x: (T, U)) -&gt; (T, U)</code>
2 changes: 1 addition & 1 deletion tests/rustdoc/where.golf_type_alias_decl.html
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
<code>pub type Golf&lt;T&gt;<span class="where fmt-newline">where
T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>,</span> = <a class="primitive" href="{{channel}}/std/primitive.tuple.html">(T, T)</a>;</code>
T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>,</span> = (T, T);</code>
2 changes: 1 addition & 1 deletion tests/rustdoc/whitespace-after-where-clause.enum.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<pre class="rust item-decl"><code>pub enum Cow&lt;'a, B&gt;<span class="where fmt-newline">where
B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a B</a>),
Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a </a>B),
Whatever(<a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>),
}</code></pre>
2 changes: 1 addition & 1 deletion tests/rustdoc/whitespace-after-where-clause.enum2.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<pre class="rust item-decl"><code>pub enum Cow2&lt;'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a B</a>),
Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a </a>B),
Whatever(<a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>),
}</code></pre>
2 changes: 1 addition & 1 deletion tests/rustdoc/whitespace-after-where-clause.struct.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<pre class="rust item-decl"><code>pub struct Struct&lt;'a, B&gt;<span class="where fmt-newline">where
B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a B</a>,
pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a </a>B,
pub b: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>,
}</code></pre>
2 changes: 1 addition & 1 deletion tests/rustdoc/whitespace-after-where-clause.struct2.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<pre class="rust item-decl"><code>pub struct Struct2&lt;'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a B</a>,
pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a </a>B,
pub b: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>,
}</code></pre>