Skip to content

unused-top-binds Warning is Disabled in the Presence of TemplateHaskell

Summary

If TemplateHaskell is enabled and a template haskell splice is used in code used by exported toplevel binds, then unused-top-binds fails to warn on any unused toplevel binds.

Steps to reproduce

Given this code:

{-# LANGUAGE TemplateHaskell #-}
module Main (main) where

import           Foo

breakTopBindCheck :: IO ()
breakTopBindCheck = let _ = $$(foo 'f') in pure ()

normalOperation :: IO ()
normalOperation = pure ()

main :: IO ()
main = run
  where
--    run = normalOperation
    run = breakTopBindCheck

And any template haskell implementation of foo. For example:

{-# LANGUAGE TemplateHaskell #-}
module Foo (foo) where

import           Language.Haskell.TH        (Q)
import           Language.Haskell.TH.Syntax (Exp (..), Lit (..), TExp (..))

foo :: Char -> Q (TExp Char)
foo c = pure $ TExp $ LitE $ CharL c

The Main module, when compiled, will fail to complain about the unused top binding for the normalOperation function. If the run definition binding to breakTopBindCheck is commented out, and the run definition binding to normalOperation is uncommented, then compiling successfully warns about the unused breakTopBindCheck binding.

Expected behavior

I expect unused top binds to result in warnings when unused top binds warnings are enabled, regardless of whether TemplateHaskell is in use.

Environment

  • GHC version used: 8.4.4

Optional:

  • Operating System: Linux, NixOS, Kernel 4.14.107
  • System Architecture: x86-64
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information