Skip to content

Documentation declarations not attached to signature module ASTs

Summary

The parser for signature modules does not include docs in the resulting AST as the parser for regular modules does.

Steps to reproduce

A fairly minimal reproducer follows.

sig-parse.cabal:

cabal-version: 3.8
name: sig-parse
version: 0.1.0

library
  build-depends:   base
  signatures:      A
  exposed-modules: B

A.hsig:

signature A where

-- | Just '()'
a :: ()
-- ^ More docs

B.hs:

module B where

-- | Just '()'
b :: ()
-- ^ More docs

Although this will fail to build due to the lack of an accompanying binding for b, it will still parse. I've made the modules as similar as possible for the sake of comparison between their ASTs.

Running cabal build --ghc-options=-haddock -ddump-to-file -ddump-parsed-ast yields the following dumps.

A.dump-parsed-ast:


==================== Parser AST ====================
2023-04-28 01:56:46.534016 UTC


(L
 { A.hsig:1:1 }
 (HsModule
  (XModulePs
   (EpAnn
    (Anchor
     { A.hsig:1:1 }
     (UnchangedAnchor))
    (AnnsModule
     [(AddEpAnn AnnSignature (EpaSpan { A.hsig:1:1-9 }))
     ,(AddEpAnn AnnWhere (EpaSpan { A.hsig:1:13-17 }))]
     (AnnList
      (Nothing)
      (Nothing)
      (Nothing)
      []
      []))
    (EpaComments
     []))
   (VirtualBraces
    (1))
   (Nothing)
   (Nothing))
  (Just
   (L
    (SrcSpanAnn (EpAnnNotUsed) { A.hsig:1:11 })
    {ModuleName: A}))
  (Nothing)
  []
  [(L
    (SrcSpanAnn (EpAnn
                 (Anchor
                  { A.hsig:4:1-7 }
                  (UnchangedAnchor))
                 (AnnListItem
                  [])
                 (EpaComments
                  [])) { A.hsig:4:1-7 })
    (SigD
     (NoExtField)
     (TypeSig
      (EpAnn
       (Anchor
        { A.hsig:4:1 }
        (UnchangedAnchor))
       (AnnSig
        (AddEpAnn AnnDcolon (EpaSpan { A.hsig:4:3-4 }))
        [])
       (EpaComments
        []))
      [(L
        (SrcSpanAnn (EpAnnNotUsed) { A.hsig:4:1 })
        (Unqual
         {OccName: a}))]
      (HsWC
       (NoExtField)
       (L
        (SrcSpanAnn (EpAnnNotUsed) { A.hsig:4:6-7 })
        (HsSig
         (NoExtField)
         (HsOuterImplicit
          (NoExtField))
         (L
          (SrcSpanAnn (EpAnnNotUsed) { A.hsig:4:6-7 })
          (HsTupleTy
           (EpAnn
            (Anchor
             { A.hsig:4:6 }
             (UnchangedAnchor))
            (AnnParen
             (AnnParens)
             (EpaSpan { A.hsig:4:6 })
             (EpaSpan { A.hsig:4:7 }))
            (EpaComments
             []))
           (HsBoxedOrConstraintTuple)
           []))))))))]))

B.dump-parsed-ast:


==================== Parser AST ====================
2023-04-28 01:56:46.556019 UTC


(L
 { B.hs:1:1 }
 (HsModule
  (XModulePs
   (EpAnn
    (Anchor
     { B.hs:1:1 }
     (UnchangedAnchor))
    (AnnsModule
     [(AddEpAnn AnnModule (EpaSpan { B.hs:1:1-6 }))
     ,(AddEpAnn AnnWhere (EpaSpan { B.hs:1:10-14 }))]
     (AnnList
      (Nothing)
      (Nothing)
      (Nothing)
      []
      []))
    (EpaCommentsBalanced
     []
     [(L
       (Anchor
        { B.hs:6:1 }
        (UnchangedAnchor))
       (EpaComment
        (EpaEofComment)
        { B.hs:6:1 }))]))
   (VirtualBraces
    (1))
   (Nothing)
   (Nothing))
  (Just
   (L
    (SrcSpanAnn (EpAnnNotUsed) { B.hs:1:8 })
    {ModuleName: B}))
  (Nothing)
  []
  [(L
    (SrcSpanAnn (EpAnnNotUsed) { B.hs:3:1-14 })
    (DocD
     (NoExtField)
     (DocCommentNext
      (L
       { B.hs:3:1-14 }
       (WithHsDocIdentifiers
        (MultiLineDocString
         (HsDocStringNext)
         (:|
          (L
           { B.hs:3:5-14 }
           (HsDocStringChunk
            " Just '()'"))
          []))
        [])))))
  ,(L
    (SrcSpanAnn (EpAnn
                 (Anchor
                  { B.hs:4:1-7 }
                  (UnchangedAnchor))
                 (AnnListItem
                  [])
                 (EpaComments
                  [])) { B.hs:4:1-7 })
    (SigD
     (NoExtField)
     (TypeSig
      (EpAnn
       (Anchor
        { B.hs:4:1 }
        (UnchangedAnchor))
       (AnnSig
        (AddEpAnn AnnDcolon (EpaSpan { B.hs:4:3-4 }))
        [])
       (EpaComments
        []))
      [(L
        (SrcSpanAnn (EpAnnNotUsed) { B.hs:4:1 })
        (Unqual
         {OccName: b}))]
      (HsWC
       (NoExtField)
       (L
        (SrcSpanAnn (EpAnnNotUsed) { B.hs:4:6-7 })
        (HsSig
         (NoExtField)
         (HsOuterImplicit
          (NoExtField))
         (L
          (SrcSpanAnn (EpAnnNotUsed) { B.hs:4:6-7 })
          (HsTupleTy
           (EpAnn
            (Anchor
             { B.hs:4:6 }
             (UnchangedAnchor))
            (AnnParen
             (AnnParens)
             (EpaSpan { B.hs:4:6 })
             (EpaSpan { B.hs:4:7 }))
            (EpaComments
             []))
           (HsBoxedOrConstraintTuple)
           []))))))))
  ,(L
    (SrcSpanAnn (EpAnnNotUsed) { B.hs:5:1-14 })
    (DocD
     (NoExtField)
     (DocCommentPrev
      (L
       { B.hs:5:1-14 }
       (WithHsDocIdentifiers
        (MultiLineDocString
         (HsDocStringPrevious)
         (:|
          (L
           { B.hs:5:5-14 }
           (HsDocStringChunk
            " More docs"))
          []))
        [])))))]))

Notice that the signature module AST (A.hsig) lacks any DocD declarations in its AST.

Expected behavior

I would expect signature module ASTs to be populated with DocD declarations, as regular modules are.

Environment

  • GHC version used: 9.6.1 (reproduced on HEAD as well)
  • Cabal version used: 3.6.2.0
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information