diff options
-rw-r--r-- | haddock-api/src/Haddock/Interface/Specialize.hs | 20 | ||||
-rw-r--r-- | html-test/ref/Bug679.html | 196 | ||||
-rw-r--r-- | html-test/src/Bug679.hs | 24 |
3 files changed, 230 insertions, 10 deletions
diff --git a/haddock-api/src/Haddock/Interface/Specialize.hs b/haddock-api/src/Haddock/Interface/Specialize.hs index 6d2888d3..bb27f10c 100644 --- a/haddock-api/src/Haddock/Interface/Specialize.hs +++ b/haddock-api/src/Haddock/Interface/Specialize.hs @@ -31,23 +31,23 @@ import qualified Data.Set as Set specialize :: forall name a. (Ord (IdP name), DataId name, NamedThing (IdP name)) => Data a => [(IdP name, HsType name)] -> a -> a -specialize specs = go +specialize specs = go spec_map0 where - go :: forall x. Data x => x -> x - go = everywhereButType @name $ mkT $ sugar . strip_kind_sig . specialize_ty_var + go :: forall x. Data x => Map name (HsType name) -> x -> x + go spec_map = everywhereButType @name $ mkT $ sugar . strip_kind_sig . specialize_ty_var spec_map strip_kind_sig :: HsType name -> HsType name strip_kind_sig (HsKindSig (L _ t) _) = t strip_kind_sig typ = typ - specialize_ty_var :: HsType name -> HsType name - specialize_ty_var (HsTyVar _ (L _ name')) + specialize_ty_var :: Map name (HsType name) -> HsType name -> HsType name + specialize_ty_var spec_map (HsTyVar _ (L _ name')) | Just t <- Map.lookup name' spec_map = t - specialize_ty_var typ = typ - -- This is a tricky recursive definition that is guaranteed to terminate - -- because a type binder cannot be instantiated with a type that depends - -- on that binder. i.e. @a -> Maybe a@ is invalid - spec_map = Map.fromList [ (n, go t) | (n, t) <- specs] + specialize_ty_var _ typ = typ + + -- This is a tricky recursive definition. By adding in the specializations + -- one by one, we should avoid infinite loops. + spec_map0 = foldr (\(n,t) acc -> Map.insert n (go acc t) acc) mempty specs -- | Instantiate given binders with corresponding types. diff --git a/html-test/ref/Bug679.html b/html-test/ref/Bug679.html new file mode 100644 index 00000000..ddec7a12 --- /dev/null +++ b/html-test/ref/Bug679.html @@ -0,0 +1,196 @@ +<html xmlns="http://www.w3.org/1999/xhtml" +><head + ><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" + /><title + >Bug679</title + ><link href="#" rel="stylesheet" type="text/css" title="Ocean" + /><link rel="stylesheet" type="text/css" href="#" + /><script src="haddock-bundle.min.js" async="async" type="text/javascript" + ></script + ><script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript" + ></script + ></head + ><body + ><div id="package-header" + ><ul class="links" id="page-menu" + ><li + ><a href="#" + >Contents</a + ></li + ><li + ><a href="#" + >Index</a + ></li + ></ul + ><p class="caption empty" + ></p + ></div + ><div id="content" + ><div id="module-header" + ><table class="info" + ><tr + ><th + >Safe Haskell</th + ><td + >None</td + ></tr + ></table + ><p class="caption" + >Bug679</p + ></div + ><div id="interface" + ><h1 + >Documentation</h1 + ><div class="top" + ><p class="src" + ><span class="keyword" + >data</span + > <a id="t:Bar" class="def" + >Bar</a + > a <a href="#" class="selflink" + >#</a + ></p + ><div class="subs constructors" + ><p class="caption" + >Constructors</p + ><table + ><tr + ><td class="src" + ><a id="v:Bar" class="def" + >Bar</a + ></td + ><td class="doc empty" + ></td + ></tr + ></table + ></div + ><div class="subs instances" + ><details id="i:Bar" open="open" + ><summary + >Instances</summary + ><table + ><tr + ><td class="src clearfix" + ><span class="inst-left" + ><span class="instance details-toggle-control details-toggle" data-details-id="i:id:Bar:Foo:1" + ></span + > <a href="#" + >Foo</a + > (<a href="#" + >Bar</a + > a)</span + > <a href="#" class="selflink" + >#</a + ></td + ><td class="doc empty" + ></td + ></tr + ><tr + ><td colspan="2" + ><details id="i:id:Bar:Foo:1" + ><summary class="hide-when-js-enabled" + >Instance details</summary + ><div class="subs methods" + ><p class="caption" + >Methods</p + ><p class="src" + ><a href="#" + >foo</a + > :: <a href="#" + >Bar</a + > a -> <a href="#" + >Bar</a + > a <a href="#" class="selflink" + >#</a + ></p + ></div + ></details + ></td + ></tr + ></table + ></details + ></div + ></div + ><div class="top" + ><p class="src" + ><span class="keyword" + >class</span + > <a id="t:Foo" class="def" + >Foo</a + > a <span class="keyword" + >where</span + > <a href="#" class="selflink" + >#</a + ></p + ><div class="subs minimal" + ><p class="caption" + >Minimal complete definition</p + ><p class="src" + ><a href="#" + >foo</a + ></p + ></div + ><div class="subs methods" + ><p class="caption" + >Methods</p + ><p class="src" + ><a id="v:foo" class="def" + >foo</a + > :: a -> a <a href="#" class="selflink" + >#</a + ></p + ></div + ><div class="subs instances" + ><details id="i:Foo" open="open" + ><summary + >Instances</summary + ><table + ><tr + ><td class="src clearfix" + ><span class="inst-left" + ><span class="instance details-toggle-control details-toggle" data-details-id="i:ic:Foo:Foo:1" + ></span + > <a href="#" + >Foo</a + > (<a href="#" + >Bar</a + > a)</span + > <a href="#" class="selflink" + >#</a + ></td + ><td class="doc empty" + ></td + ></tr + ><tr + ><td colspan="2" + ><details id="i:ic:Foo:Foo:1" + ><summary class="hide-when-js-enabled" + >Instance details</summary + ><div class="subs methods" + ><p class="caption" + >Methods</p + ><p class="src" + ><a href="#" + >foo</a + > :: <a href="#" + >Bar</a + > a -> <a href="#" + >Bar</a + > a <a href="#" class="selflink" + >#</a + ></p + ></div + ></details + ></td + ></tr + ></table + ></details + ></div + ></div + ></div + ></div + ><div id="footer" + ></div + ></body + ></html +>
\ No newline at end of file diff --git a/html-test/src/Bug679.hs b/html-test/src/Bug679.hs new file mode 100644 index 00000000..dba194c4 --- /dev/null +++ b/html-test/src/Bug679.hs @@ -0,0 +1,24 @@ +{-# LANGUAGE TemplateHaskell #-} + +module Bug679 where + +import Language.Haskell.TH + +data Bar a = Bar + +$(do + a <- newName "a" + + let classN = mkName "Foo" + let methodN = mkName "foo" + + methodTy <- [t| $(varT a) -> $(varT a) |] + let cla = ClassD [] classN [PlainTV a] [] [SigD methodN methodTy] + + -- Note that we are /reusing/ the same type variable 'a' as in the class + instanceHead <- [t| $(conT classN) (Bar $(varT a)) |] + idCall <- [e| id |] + let ins = InstanceD Nothing [] instanceHead [FunD methodN [Clause [] (NormalB idCall) []]] + + pure [cla,ins]) + |