首页 > 解决方案 > 插件名称查找行为从 GHC 8.4 系列更改

问题描述

[更新:原来这是一个 GHC 错误,现在已修复,计划在 8.6.4 版本中发布:https ://ghc.haskell.org/trac/ghc/ticket/16104#comment:8 ]

我正在尝试将核心插件移植到 GHC 8.6.3,该插件最后在 GHC 8.4 系列上运行良好。不幸的是,我遇到了问题。想知道插件编程要求是否已经改变,或者这是 GHC 本身的回归。我将其归结为以下示例,并希望获得有关如何使其工作的一些指导:

我在文件中有以下内容TestPlugin.hs

{-# LANGUAGE TemplateHaskell #-}

module TestPlugin (plugin) where

import GhcPlugins
import Data.Bits

plugin :: Plugin
plugin = defaultPlugin {installCoreToDos = install}
  where install _ todos = return (test : todos)

        test = CoreDoPluginPass "Test" check

        check :: ModGuts -> CoreM ModGuts
        check m = do mbN <- thNameToGhcName 'complement
                     case mbN of
                       Just _  -> liftIO $ putStrLn "Found complement!"
                       Nothing -> error "Failed to locate complement"

                     return m

我有一个非常简单的Test.hs文件:

{-# OPTIONS_GHC -fplugin TestPlugin #-}

main :: IO ()
main = return ()

使用 GHC-8.4.2,我有:

$ ghc-8.4.2 --make -package ghc -c TestPlugin.hs
[1 of 1] Compiling TestPlugin       ( TestPlugin.hs, TestPlugin.o )

$ ghc-8.4.2 -package ghc -c Test.hs
Found complement!

但是使用 GHC 8.6.3,我得到:

$ ghc-8.6.3 --make -package ghc -c TestPlugin.hs
[1 of 1] Compiling TestPlugin       ( TestPlugin.hs, TestPlugin.o )

$ ghc-8.6.3 -package ghc -c Test.hs
ghc: panic! (the 'impossible' happened)
  (GHC version 8.6.3 for x86_64-apple-darwin):
    Failed to locate complement

如果我Test.hs改为:

{-# OPTIONS_GHC -fplugin TestPlugin #-}

import Data.Bits  -- Should not be required in the client code!

main :: IO ()
main = return ()

也就是说,如果我明确导入Data.Bits. 但是这是非常不可取的,因为Test.hs客户端代码和插件的用户没有理由导入插件可能需要的所有模块。(实际上,这将需要客户端导入一大堆不相关的模块;非常不可行且不可维护。)

我发现了以下堆栈溢出票证,它似乎遇到了类似的问题:How to replication the behavior of 'name in a TH splice然而,答案表明在这种情况下是不行的(也许不是'那里也真的没问题),因为在我的情况下,它需要对客户端代码进行不必要的更改,这是不合理的预期。(也许@JoachimBretner 有一个想法?)我也将此作为 GHC 票(https://ghc.haskell.org/trac/ghc/ticket/16104#ticket)提交,但来自 stack-overflow 社区的反馈是非常感激。

我应该以不同的方式编码我的插件吗?或者这是一个 GHC 回归?

标签: haskell

解决方案


不是直接的答案,但是当我需要在 GHC 插件中“硬编码”一个名称时,我不使用 TH。相反,我使用findImportedModuleandlookupOrig来查找它,例如

lookupJDITyCon :: TcPluginM Class
lookupJDITyCon = do
    Found _ md   <- findImportedModule jdiModule Nothing
    jdiTcNm <- lookupOrig md (mkTcOcc "JustDoIt")
    tcLookupClass jdiTcNm
  where
jdiModule = mkModuleName "GHC.JustDoIt"

从我的ghc-justdoit插件的代码。

当用户需要提及名称时,我使用 Template Haskell 名称,例如在拼接或注释中,我想在插件中获取这些名称。这就是我在inspection-testing. 我在检查测试论文的附录中对此进行了一些讨论。


推荐阅读