Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#9871 closed bug (fixed)

Template Haskell declaration splice causes subsequent declarations to fall out of scope

Reported by: RyanGlScott Owned by:
Priority: normal Milestone:
Component: Documentation Version: 7.8.3
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: GHC rejects valid program Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description

When using Template Haskell to splice in instance declarations, it is possible to cause identifiers following it to fall out of scope:

-- DeriveJSON.hs
{-# LANGUAGE TemplateHaskell #-}
module DeriveJSON where

import Data.Aeson.TH

data ADT = ADT

instance Show ADT
    where show = adtFun

$(deriveJSON defaultOptions ''ADT)

adtFun :: ADT -> String
adtFun = undefined

ghc DeriveJSON.hs gives the following error:

[1 of 1] Compiling DeriveJSON       ( DeriveJSON.hs, DeriveJSON.o )

DeriveJSON.hs:10:18: Not in scope: ‘adtFun’

Since deriveJSON simply returns a Q [Dec], I don't see why this code shouldn't compile as is.

I can find two workarounds at the moment:

  • Move the instance Show ADT declaration after the $(deriveJSON defaultOptions ''ADT) line.
  • Move the $(deriveJSON defaultOptions ''ADT) line after the adtFun function declaration.

Change History (4)

comment:1 Changed 3 years ago by Richard Eisenberg <eir@…>

In b06908b5a120ed56df5416019c38576aadcd21e2/ghc:

Fix #9871 by clarifying documentation.

comment:2 Changed 3 years ago by goldfire

Component: Template HaskellDocumentation
Resolution: fixed
Status: newclosed

This is by design, but I've tweaked the TH documentation to make this more apparent. A top-level declaration splice (your $(deriveJSON ... )) breaks up the mutual recursion among all top-level declarations. Code above the splice can't see code below it. This allows code within the splice to see some definitions in your file, and code after the splice to see the definitions in the splice itself.

Thanks for reporting!

comment:3 Changed 3 years ago by RyanGlScott

Just to clarify, which of the above workarounds would you recommend? Should I move all TH declaration splices to the top or bottom of the module? Something else?

comment:4 Changed 3 years ago by goldfire

It's up to you and what works with your coding style. I can't really recommend one ordering over another.

Note: See TracTickets for help on using tickets.