From d0284590978f4fefd3c6845e628f8efa2100ac34 Mon Sep 17 00:00:00 2001
From: Gil Mizrahi <gilmi@posteo.net>
Date: Tue, 5 Jan 2021 13:14:44 +0200
Subject: [PATCH] Fix #1206 by passing instance name as anchor

(cherry picked from commit 88106cbe72b6a444a9b335ee53089d8eac503bd7)
---
 .../src/Haddock/Backends/Xhtml/Decl.hs        |  15 +-
 .../src/Haddock/Backends/Xhtml/Layout.hs      |  10 +-
 html-test/ref/Bug1206.html                    | 483 ++++++++++++++++++
 html-test/src/Bug1206.hs                      |  43 ++
 4 files changed, 541 insertions(+), 10 deletions(-)
 create mode 100644 html-test/ref/Bug1206.html
 create mode 100644 html-test/src/Bug1206.hs

diff --git a/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs b/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
index 0b0050df5f..19fe5abde7 100644
--- a/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
+++ b/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
@@ -634,10 +634,12 @@ ppInstances links origin instances splice unicode pkg qual
   -- force Splice = True to use line URLs
   where
     instName = getOccString origin
-    instDecl :: Int -> DocInstance DocNameI -> (SubDecl, Maybe Module, Located DocName)
+    instDecl :: Int -> DocInstance DocNameI -> (String, SubDecl, Maybe Module, Located DocName)
     instDecl no (inst, mdoc, loc, mdl) =
-        ((ppInstHead links splice unicode qual mdoc origin False no inst mdl), mdl, loc)
-
+        (instanceAnchor, mModule, mdl, loc)
+      where
+        instanceAnchor = getOccString (ihdClsName inst) <> "_" <> show no <> ":"
+        mModule = ppInstHead links splice unicode qual mdoc origin False no inst mdl
 
 ppOrphanInstances :: LinksInfo
                   -> [DocInstance DocNameI]
@@ -649,9 +651,12 @@ ppOrphanInstances links instances splice unicode pkg qual
     instOrigin :: InstHead name -> InstOrigin (IdP name)
     instOrigin inst = OriginClass (ihdClsName inst)
 
-    instDecl :: Int -> DocInstance DocNameI -> (SubDecl, Maybe Module, Located DocName)
+    instDecl :: Int -> DocInstance DocNameI -> (String, SubDecl, Maybe Module, Located DocName)
     instDecl no (inst, mdoc, loc, mdl) =
-        ((ppInstHead links splice unicode qual mdoc (instOrigin inst) True no inst Nothing), mdl, loc)
+        (instanceAnchor, mModule, mdl, loc)
+      where
+        instanceAnchor = getOccString (ihdClsName inst) <> "_" <> show no <> ":"
+        mModule = ppInstHead links splice unicode qual mdoc (instOrigin inst) True no inst Nothing
 
 
 ppInstHead :: LinksInfo -> Splice -> Unicode -> Qualification
diff --git a/haddock-api/src/Haddock/Backends/Xhtml/Layout.hs b/haddock-api/src/Haddock/Backends/Xhtml/Layout.hs
index d61d6d9bb8..e646fdc4bc 100644
--- a/haddock-api/src/Haddock/Backends/Xhtml/Layout.hs
+++ b/haddock-api/src/Haddock/Backends/Xhtml/Layout.hs
@@ -153,16 +153,16 @@ subTable pkg qual decls = Just $ table << aboves (concatMap subRow decls)
 
 -- | Sub table with source information (optional).
 subTableSrc :: Maybe Package -> Qualification -> LinksInfo -> Bool
-            -> [(SubDecl, Maybe Module, Located DocName)] -> Maybe Html
+            -> [(String, SubDecl, Maybe Module, Located DocName)] -> Maybe Html
 subTableSrc _ _ _ _ [] = Nothing
 subTableSrc pkg qual lnks splice decls = Just $ table << aboves (concatMap subRow decls)
   where
-    subRow ((decl, mdoc, subs), mdl, L loc dn) =
+    subRow (instanchor, (decl, mdoc, subs), mdl, L loc dn) =
       (td ! [theclass "src clearfix"] <<
         (thespan ! [theclass "inst-left"] << decl)
         <+> linkHtml loc mdl dn
       <->
-      docElement td << fmap (docToHtml Nothing pkg qual) mdoc
+      docElement td << fmap (docToHtml (Just instanchor) pkg qual) mdoc
       )
       : map (cell . (td <<)) subs
 
@@ -201,7 +201,7 @@ subEquations pkg qual = divSubDecls "equations" "Equations" . subTable pkg qual
 subInstances :: Maybe Package -> Qualification
              -> String -- ^ Class name, used for anchor generation
              -> LinksInfo -> Bool
-             -> [(SubDecl, Maybe Module, Located DocName)] -> Html
+             -> [(String, SubDecl, Maybe Module, Located DocName)] -> Html
 subInstances pkg qual nm lnks splice = maybe noHtml wrap . instTable
   where
     wrap contents = subSection (hdr +++ collapseDetails id_ DetailsOpen (summary +++ contents))
@@ -214,7 +214,7 @@ subInstances pkg qual nm lnks splice = maybe noHtml wrap . instTable
 
 subOrphanInstances :: Maybe Package -> Qualification
                    -> LinksInfo -> Bool
-                   -> [(SubDecl, Maybe Module, Located DocName)] -> Html
+                   -> [(String, SubDecl, Maybe Module, Located DocName)] -> Html
 subOrphanInstances pkg qual lnks splice  = maybe noHtml wrap . instTable
   where
     wrap = ((h1 << "Orphan instances") +++)
diff --git a/html-test/ref/Bug1206.html b/html-test/ref/Bug1206.html
new file mode 100644
index 0000000000..4b0a28e9ef
--- /dev/null
+++ b/html-test/ref/Bug1206.html
@@ -0,0 +1,483 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+><head
+  ><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"
+     /><meta name="viewport" content="width=device-width, initial-scale=1"
+     /><title
+    >Bug1206</title
+    ><link href="#" rel="stylesheet" type="text/css" title="Linuwial"
+     /><link rel="stylesheet" type="text/css" href="#"
+     /><link rel="stylesheet" type="text/css" href="#"
+     /><script src="haddock-bundle.min.js" async="async" type="text/javascript"
+    ></script
+    ><script type="text/x-mathjax-config"
+    >MathJax.Hub.Config({ tex2jax: { processClass: "mathjax", ignoreClass: ".*" } });</script
+    ><script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"
+    ></script
+    ></head
+  ><body
+  ><div id="package-header"
+    ><span class="caption empty"
+      >&nbsp;</span
+      ><ul class="links" id="page-menu"
+      ><li
+	><a href="#"
+	  >Contents</a
+	  ></li
+	><li
+	><a href="#"
+	  >Index</a
+	  ></li
+	></ul
+      ></div
+    ><div id="content"
+    ><div id="module-header"
+      ><table class="info"
+	><tr
+	  ><th
+	    >Safe Haskell</th
+	    ><td
+	    >Safe-Inferred</td
+	    ></tr
+	  ></table
+	><p class="caption"
+	>Bug1206</p
+	></div
+      ><div id="description"
+      ><p class="caption"
+	>Description</p
+	><div class="doc"
+	><p
+	  >Bug 1206</p
+	  ></div
+	></div
+      ><div id="synopsis"
+      ><details id="syn"
+	><summary
+	  >Synopsis</summary
+	  ><ul class="details-toggle" data-details-id="syn"
+	  ><li class="src short"
+	    ><span class="keyword"
+	      >data</span
+	      > <a href="#"
+	      >T</a
+	      > a = <a href="#"
+	      >T</a
+	      > a</li
+	    ></ul
+	  ></details
+	></div
+      ><div id="interface"
+      ><h1
+	>Documentation</h1
+	><div class="top"
+	><p class="src"
+	  ><span class="keyword"
+	    >data</span
+	    > <a id="t:T" class="def"
+	    >T</a
+	    > a <a href="#" class="selflink"
+	    >#</a
+	    ></p
+	  ><div class="doc"
+	  ><p
+	    >A simple identity type</p
+	    ></div
+	  ><div class="subs constructors"
+	  ><p class="caption"
+	    >Constructors</p
+	    ><table
+	    ><tr
+	      ><td class="src"
+		><a id="v:T" class="def"
+		  >T</a
+		  > a</td
+		><td class="doc empty"
+		>&nbsp;</td
+		></tr
+	      ></table
+	    ></div
+	  ><div class="subs instances"
+	  ><h4 class="instances details-toggle-control details-toggle" data-details-id="i:T"
+	    >Instances</h4
+	    ><details id="i:T" open="open"
+	    ><summary class="hide-when-js-enabled"
+	      >Instances details</summary
+	      ><table
+	      ><tr
+		><td class="src clearfix"
+		  ><span class="inst-left"
+		    ><span class="instance details-toggle-control details-toggle" data-details-id="i:id:T:Show:1"
+		      ></span
+		      > <a href="#" title="Text.Show"
+		      >Show</a
+		      > a =&gt; <a href="#" title="Text.Show"
+		      >Show</a
+		      > (<a href="#" title="Bug1206"
+		      >T</a
+		      > a)</span
+		    > <a href="#" class="selflink"
+		    >#</a
+		    ></td
+		  ><td class="doc empty"
+		  >&nbsp;</td
+		  ></tr
+		><tr
+		><td colspan="2"
+		  ><details id="i:id:T:Show:1"
+		    ><summary class="hide-when-js-enabled"
+		      >Instance details</summary
+		      ><p
+		      >Defined in <a href="#"
+			>Bug1206</a
+			></p
+		      > <div class="subs methods"
+		      ><p class="caption"
+			>Methods</p
+			><p class="src"
+			><a href="#"
+			  >showsPrec</a
+			  > :: <a href="#" title="Data.Int"
+			  >Int</a
+			  > -&gt; <a href="#" title="Bug1206"
+			  >T</a
+			  > a -&gt; <a href="#" title="Text.Show"
+			  >ShowS</a
+			  > <a href="#" class="selflink"
+			  >#</a
+			  ></p
+			><p class="src"
+			><a href="#"
+			  >show</a
+			  > :: <a href="#" title="Bug1206"
+			  >T</a
+			  > a -&gt; <a href="#" title="Data.String"
+			  >String</a
+			  > <a href="#" class="selflink"
+			  >#</a
+			  ></p
+			><p class="src"
+			><a href="#"
+			  >showList</a
+			  > :: [<a href="#" title="Bug1206"
+			  >T</a
+			  > a] -&gt; <a href="#" title="Text.Show"
+			  >ShowS</a
+			  > <a href="#" class="selflink"
+			  >#</a
+			  ></p
+			></div
+		      ></details
+		    ></td
+		  ></tr
+		><tr
+		><td class="src clearfix"
+		  ><span class="inst-left"
+		    ><span class="instance details-toggle-control details-toggle" data-details-id="i:id:T:Semigroup:2"
+		      ></span
+		      > <a href="#" title="Prelude"
+		      >Semigroup</a
+		      > (<a href="#" title="Bug1206"
+		      >T</a
+		      > <a href="#" title="Data.Int"
+		      >Int</a
+		      >)</span
+		    > <a href="#" class="selflink"
+		    >#</a
+		    ></td
+		  ><td class="doc"
+		  ><p
+		    ><code
+		      ><a href="#" title="Data.Monoid"
+			>&lt;&gt;</a
+			></code
+		      > = 'T (a + b)'</p
+		    ><p
+		    >Docs for the <code
+		      >Semigroup</code
+		      > instance of <code
+		      >(T Int)</code
+		      ></p
+		    ><h4 class="subheading details-toggle-control details-toggle" data-details-id="ch:Semigroup_2:0"
+		    >Examples</h4
+		    ><details id="ch:Semigroup_2:0"
+		    ><summary class="hide-when-js-enabled"
+		      >Expand</summary
+		      ><pre class="screen"
+		      ><code class="prompt"
+			>&gt;&gt;&gt; </code
+			><strong class="userinput"
+			><code
+			  >T 2 &lt;&gt; T (3 :: Int)
+</code
+			  ></strong
+			>T 5
+</pre
+		      ></details
+		    ></td
+		  ></tr
+		><tr
+		><td colspan="2"
+		  ><details id="i:id:T:Semigroup:2"
+		    ><summary class="hide-when-js-enabled"
+		      >Instance details</summary
+		      ><p
+		      >Defined in <a href="#"
+			>Bug1206</a
+			></p
+		      > <div class="subs methods"
+		      ><p class="caption"
+			>Methods</p
+			><p class="src"
+			><a href="#"
+			  >(&lt;&gt;)</a
+			  > :: <a href="#" title="Bug1206"
+			  >T</a
+			  > <a href="#" title="Data.Int"
+			  >Int</a
+			  > -&gt; <a href="#" title="Bug1206"
+			  >T</a
+			  > <a href="#" title="Data.Int"
+			  >Int</a
+			  > -&gt; <a href="#" title="Bug1206"
+			  >T</a
+			  > <a href="#" title="Data.Int"
+			  >Int</a
+			  > <a href="#" class="selflink"
+			  >#</a
+			  ></p
+			><p class="src"
+			><a href="#"
+			  >sconcat</a
+			  > :: <a href="#" title="Data.List.NonEmpty"
+			  >NonEmpty</a
+			  > (<a href="#" title="Bug1206"
+			  >T</a
+			  > <a href="#" title="Data.Int"
+			  >Int</a
+			  >) -&gt; <a href="#" title="Bug1206"
+			  >T</a
+			  > <a href="#" title="Data.Int"
+			  >Int</a
+			  > <a href="#" class="selflink"
+			  >#</a
+			  ></p
+			><p class="src"
+			><a href="#"
+			  >stimes</a
+			  > :: <a href="#" title="Prelude"
+			  >Integral</a
+			  > b =&gt; b -&gt; <a href="#" title="Bug1206"
+			  >T</a
+			  > <a href="#" title="Data.Int"
+			  >Int</a
+			  > -&gt; <a href="#" title="Bug1206"
+			  >T</a
+			  > <a href="#" title="Data.Int"
+			  >Int</a
+			  > <a href="#" class="selflink"
+			  >#</a
+			  ></p
+			></div
+		      ></details
+		    ></td
+		  ></tr
+		><tr
+		><td class="src clearfix"
+		  ><span class="inst-left"
+		    ><span class="instance details-toggle-control details-toggle" data-details-id="i:id:T:Semigroup:3"
+		      ></span
+		      > <a href="#" title="Prelude"
+		      >Semigroup</a
+		      > a =&gt; <a href="#" title="Prelude"
+		      >Semigroup</a
+		      > (<a href="#" title="Bug1206"
+		      >T</a
+		      > a)</span
+		    > <a href="#" class="selflink"
+		    >#</a
+		    ></td
+		  ><td class="doc"
+		  ><p
+		    ><code
+		      ><a href="#" title="Data.Monoid"
+			>&lt;&gt;</a
+			></code
+		      > = 'T (a &lt;&gt; b)'</p
+		    ><p
+		    >Docs for the <code
+		      >Semigroup</code
+		      > instance of <code
+		      >Semigroup a =&gt; T a</code
+		      ></p
+		    ><h4 class="subheading details-toggle-control details-toggle" data-details-id="ch:Semigroup_3:0"
+		    >Examples</h4
+		    ><details id="ch:Semigroup_3:0"
+		    ><summary class="hide-when-js-enabled"
+		      >Expand</summary
+		      ><pre class="screen"
+		      ><code class="prompt"
+			>&gt;&gt;&gt; </code
+			><strong class="userinput"
+			><code
+			  >T (Product 1) &lt;&gt; T (Product 2)
+</code
+			  ></strong
+			>T (Product {getProduct = 2})
+</pre
+		      ></details
+		    ></td
+		  ></tr
+		><tr
+		><td colspan="2"
+		  ><details id="i:id:T:Semigroup:3"
+		    ><summary class="hide-when-js-enabled"
+		      >Instance details</summary
+		      ><p
+		      >Defined in <a href="#"
+			>Bug1206</a
+			></p
+		      > <div class="subs methods"
+		      ><p class="caption"
+			>Methods</p
+			><p class="src"
+			><a href="#"
+			  >(&lt;&gt;)</a
+			  > :: <a href="#" title="Bug1206"
+			  >T</a
+			  > a -&gt; <a href="#" title="Bug1206"
+			  >T</a
+			  > a -&gt; <a href="#" title="Bug1206"
+			  >T</a
+			  > a <a href="#" class="selflink"
+			  >#</a
+			  ></p
+			><p class="src"
+			><a href="#"
+			  >sconcat</a
+			  > :: <a href="#" title="Data.List.NonEmpty"
+			  >NonEmpty</a
+			  > (<a href="#" title="Bug1206"
+			  >T</a
+			  > a) -&gt; <a href="#" title="Bug1206"
+			  >T</a
+			  > a <a href="#" class="selflink"
+			  >#</a
+			  ></p
+			><p class="src"
+			><a href="#"
+			  >stimes</a
+			  > :: <a href="#" title="Prelude"
+			  >Integral</a
+			  > b =&gt; b -&gt; <a href="#" title="Bug1206"
+			  >T</a
+			  > a -&gt; <a href="#" title="Bug1206"
+			  >T</a
+			  > a <a href="#" class="selflink"
+			  >#</a
+			  ></p
+			></div
+		      ></details
+		    ></td
+		  ></tr
+		><tr
+		><td class="src clearfix"
+		  ><span class="inst-left"
+		    ><span class="instance details-toggle-control details-toggle" data-details-id="i:id:T:Monoid:4"
+		      ></span
+		      > <a href="#" title="Data.Monoid"
+		      >Monoid</a
+		      > a =&gt; <a href="#" title="Data.Monoid"
+		      >Monoid</a
+		      > (<a href="#" title="Bug1206"
+		      >T</a
+		      > a)</span
+		    > <a href="#" class="selflink"
+		    >#</a
+		    ></td
+		  ><td class="doc"
+		  ><p
+		    ><code
+		      ><a href="#" title="Data.Monoid"
+			>mempty</a
+			></code
+		      > = 'T mempty'</p
+		    ><p
+		    >Docs for the <code
+		      >Monoid</code
+		      > instance of <code
+		      >Monoid a =&gt; T a</code
+		      ></p
+		    ><h4 class="subheading details-toggle-control details-toggle" data-details-id="ch:Monoid_4:0"
+		    >Examples</h4
+		    ><details id="ch:Monoid_4:0"
+		    ><summary class="hide-when-js-enabled"
+		      >Expand</summary
+		      ><pre class="screen"
+		      ><code class="prompt"
+			>&gt;&gt;&gt; </code
+			><strong class="userinput"
+			><code
+			  >mempty :: T String
+</code
+			  ></strong
+			>T &quot;&quot;
+</pre
+		      ></details
+		    ></td
+		  ></tr
+		><tr
+		><td colspan="2"
+		  ><details id="i:id:T:Monoid:4"
+		    ><summary class="hide-when-js-enabled"
+		      >Instance details</summary
+		      ><p
+		      >Defined in <a href="#"
+			>Bug1206</a
+			></p
+		      > <div class="subs methods"
+		      ><p class="caption"
+			>Methods</p
+			><p class="src"
+			><a href="#"
+			  >mempty</a
+			  > :: <a href="#" title="Bug1206"
+			  >T</a
+			  > a <a href="#" class="selflink"
+			  >#</a
+			  ></p
+			><p class="src"
+			><a href="#"
+			  >mappend</a
+			  > :: <a href="#" title="Bug1206"
+			  >T</a
+			  > a -&gt; <a href="#" title="Bug1206"
+			  >T</a
+			  > a -&gt; <a href="#" title="Bug1206"
+			  >T</a
+			  > a <a href="#" class="selflink"
+			  >#</a
+			  ></p
+			><p class="src"
+			><a href="#"
+			  >mconcat</a
+			  > :: [<a href="#" title="Bug1206"
+			  >T</a
+			  > a] -&gt; <a href="#" title="Bug1206"
+			  >T</a
+			  > a <a href="#" class="selflink"
+			  >#</a
+			  ></p
+			></div
+		      ></details
+		    ></td
+		  ></tr
+		></table
+	      ></details
+	    ></div
+	  ></div
+	></div
+      ></div
+    ></body
+  ></html
+>
diff --git a/html-test/src/Bug1206.hs b/html-test/src/Bug1206.hs
new file mode 100644
index 0000000000..600af0e825
--- /dev/null
+++ b/html-test/src/Bug1206.hs
@@ -0,0 +1,43 @@
+{- | Bug 1206
+-}
+
+{-# language FlexibleInstances #-}
+
+module Bug1206 where
+
+-- | A simple identity type
+data T a = T a
+  deriving Show
+
+-- | '<>' = 'T (a + b)'
+--
+-- Docs for the @Semigroup@ instance of @(T Int)@
+--
+-- ==== __Examples__
+--
+-- >>> T 2 <> T (3 :: Int)
+-- T 5
+instance {-# overlapping #-} Semigroup (T Int) where
+  (<>) (T a) (T b) = T (a + b)
+
+-- | '<>' = 'T (a <> b)'
+--
+-- Docs for the @Semigroup@ instance of @Semigroup a => T a@
+--
+-- ==== __Examples__
+--
+-- >>> T (Product 1) <> T (Product 2)
+-- T (Product {getProduct = 2})
+instance {-# overlapping #-} Semigroup a => Semigroup (T a) where
+  (<>) (T a) (T b) = T (a <> b)
+
+-- | 'mempty' = 'T mempty'
+--
+-- Docs for the @Monoid@ instance of @Monoid a => T a@
+--
+-- ==== __Examples__
+--
+-- >>> mempty :: T String
+-- T ""
+instance Monoid a => Monoid (T a) where
+  mempty = T mempty
-- 
GitLab