Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 5,242
    • Issues 5,242
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 567
    • Merge requests 567
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Releases
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Glasgow Haskell CompilerGlasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #21730
Closed
Open
Issue created Jun 14, 2022 by Brandon Chinn@brandonchinn178Developer

Adding import in GHC plugin shows unused-import

Summary

In a compiler plugin, I'm hooking into parsedActionResult to modify the module being compiled. I'm adding an import and then using something from the import, but GHC still complains about unused-import.

Update 1: It seems like this happens because of generatedSrcSpan. See Reddit thread for more details.

More generally, is there a way to use an identifier without needing to import it? I know with Template Haskell, if you use a ticked Name, it'll resolve successfully, even if it's not imported.

Original Reddit post: https://www.reddit.com/r/haskell/comments/vbwuzk/writing_a_ghc_plugin_autogenerated_import/

Steps to reproduce

Minimal repro:

module Plugin (plugin) where

import GHC.Hs
import GHC.Plugins
import qualified GHC.Types.Name.Occurrence as NameSpace

plugin :: Plugin
plugin =
  defaultPlugin
    { parsedResultAction = \_ _ modl -> pure modl{hpm_module = update <$> hpm_module modl}
    }

update :: HsModule -> HsModule
update modl =
  modl
    { hsmodImports =
        [ genLoc $ simpleImportDecl $ mkModuleName "Data.List"
        ]
    , hsmodDecls =
        [ genLoc . genFuncDecl (mkRdrName "intercalate2") [] $
            genLoc $ HsVar NoExtField (mkRdrName "intercalate")
        ]
    }

-- | Make simple function declaration of the form `<funcName> <funcArgs> = <funcBody>`
genFuncDecl :: Located RdrName ->  [LPat GhcPs] -> LHsExpr GhcPs -> HsDecl GhcPs
genFuncDecl funcName funcArgs funcBody =
  (\body -> ValD NoExtField $ FunBind NoExtField funcName body [])
    . (\match -> MG NoExtField (genLoc [genLoc match]) Generated)
    . Match NoExtField (FunRhs funcName Prefix NoSrcStrict) funcArgs
    . (\grhs -> GRHSs NoExtField [genLoc grhs] funcWhere)
    $ GRHS NoExtField [] funcBody
  where
    funcWhere = genLoc $ EmptyLocalBinds NoExtField

genLoc :: e -> Located e
genLoc = L generatedSrcSpan

mkRdrName :: String -> Located RdrName
mkRdrName = genLoc . mkRdrUnqual . mkOccName NameSpace.varName
{-# OPTIONS_GHC -fplugin=Plugin #-}
module Foo where
stack ghc --resolver=ghc-9.0 --package ghc -- Foo.hs -Wunused-imports -Werror -dynamic-too

Expected behavior

This should generate the equivalent of

module Foo where
import Data.List
intercalate2 = intercalate

So Data.List is being used; indeed, when removing the import, the use of intercalate fails. So Data.List shouldn't be marked unused.

Environment

  • GHC version used: 9.0 (I haven't tested with 9.2 because I'm using the 9.0 version of the GHC API, and I didn't want to update it to 9.2 yet)

Optional:

  • Operating System:
  • System Architecture:
Edited Jun 14, 2022 by Brandon Chinn
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking