about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-04-04 09:27:46 -0700
committerGitHub <noreply@github.com>2023-04-04 09:27:46 -0700
commit72e535ea992b7a1d831f9cd634090ab9cc35b9b7 (patch)
tree404910f90c02ad61182b37a9d4ff4d92029ec188
parenta5c395ed947daaf5582296188f06171ff12a9240 (diff)
parent6567bc9a4778d44cb46b7732aec6452358c62312 (diff)
downloadrust-72e535ea992b7a1d831f9cd634090ab9cc35b9b7.tar.gz
rust-72e535ea992b7a1d831f9cd634090ab9cc35b9b7.zip
Rollup merge of #109919 - fmease:rustdoc-fix-issue-109488, r=notriddle
rustdoc: escape GAT args in more cases

Fixes #109488.

Previously we printed the *un*escaped form of GAT arguments not only when `f.alternate()` was true but *also* when we failed to compute the URL of the trait associated with the type projection, i.e. when `href(…)` returned an `Err(_)`.

In this PR the argument printing logic is entirely separate from the link resolution code above as it should be.
Further, we now only try to compute the URL if the HTML format was requested with `!f.alternate()`. Before, we would sometimes compute the `href` only to throw it away later.
-rw-r--r--src/librustdoc/html/format.rs31
-rw-r--r--tests/rustdoc/generic-associated-types/issue-109488.rs18
2 files changed, 33 insertions, 16 deletions
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 0895bb510d4..02b358e863b 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -1142,22 +1142,21 @@ fn fmt_type<'cx>(
             //        the ugliness comes from inlining across crates where
             //        everything comes in as a fully resolved QPath (hard to
             //        look at).
-            match href(trait_.def_id(), cx) {
-                Ok((ref url, _, ref path)) if !f.alternate() => {
-                    write!(
-                        f,
-                        "<a class=\"associatedtype\" href=\"{url}#{shortty}.{name}\" \
-                                    title=\"type {path}::{name}\">{name}</a>{args}",
-                        url = url,
-                        shortty = ItemType::AssocType,
-                        name = assoc.name,
-                        path = join_with_double_colon(path),
-                        args = assoc.args.print(cx),
-                    )?;
-                }
-                _ => write!(f, "{}{:#}", assoc.name, assoc.args.print(cx))?,
-            }
-            Ok(())
+            if !f.alternate() && let Ok((url, _, path)) = href(trait_.def_id(), cx) {
+                write!(
+                    f,
+                    "<a class=\"associatedtype\" href=\"{url}#{shortty}.{name}\" \
+                                title=\"type {path}::{name}\">{name}</a>",
+                    shortty = ItemType::AssocType,
+                    name = assoc.name,
+                    path = join_with_double_colon(&path),
+                )
+            } else {
+                write!(f, "{}", assoc.name)
+            }?;
+
+            // Carry `f.alternate()` into this display w/o branching manually.
+            fmt::Display::fmt(&assoc.args.print(cx), f)
         }
     }
 }
diff --git a/tests/rustdoc/generic-associated-types/issue-109488.rs b/tests/rustdoc/generic-associated-types/issue-109488.rs
new file mode 100644
index 00000000000..99ae8a6c36c
--- /dev/null
+++ b/tests/rustdoc/generic-associated-types/issue-109488.rs
@@ -0,0 +1,18 @@
+// Make sure that we escape the arguments of the GAT projection even if we fail to compute
+// the href of the corresponding trait (in this case it is private).
+// Further, test that we also linkify the GAT arguments.
+
+// @has 'issue_109488/type.A.html'
+// @has - '//pre[@class="rust item-decl"]' '<S as Tr>::P<Option<i32>>'
+// @has - '//pre[@class="rust item-decl"]//a[@class="enum"]/@href' '{{channel}}/core/option/enum.Option.html'
+pub type A = <S as Tr>::P<Option<i32>>;
+
+/*private*/ trait Tr {
+    type P<T>;
+}
+
+pub struct S;
+
+impl Tr for S {
+    type P<T> = ();
+}