如何在GHC类型检查器插件中"机会性"查找已加载定义?
GHC类型检查器插件中查找已加载定义的合规方式
针对你遇到的findImportedModule的问题,推荐使用以下稳妥的合规方案,核心思路是先确认目标模块已加载到当前环境,再安全查找对应名称:
1. 检查模块是否已加载
通过getTopEnv获取当前环境的HscEnv,直接查询GHC维护的已加载单元集合:
import GHC import GHC.Types.Name.Occurrence import GHC.Tc.Plugin (TcPluginM, getTopEnv) import GHC.Unit.State (lookupModuleInHomeUnit, lookupModuleInUnits) import GHC.Unit.Types (Module, ModuleName) isModuleLoaded :: Module -> TcPluginM Bool isModuleLoaded target_mod = do hsc_env <- getTopEnv let hsc_units = hsc_units hsc_env -- 先检查当前本地单元是否加载了该模块 home_match = lookupModuleInHomeUnit hsc_units (moduleName target_mod) -- 再检查依赖单元中是否加载了该模块 dep_match = lookupModuleInUnits hsc_units (moduleName target_mod) (moduleUnit target_mod) return $ case (home_match, dep_match) of (Just _, _) -> True (_, Just _) -> True _ -> False
2. 安全查找模块内的名称
确认模块已加载后,调用lookupOrig查找目标名称,此时不会出现模块未加载的报错:
lookupOrigSafe :: Module -> OccName -> TcPluginM (Maybe Name) lookupOrigSafe mod occ = do loaded <- isModuleLoaded mod if not loaded then return Nothing else Just <$> lookupOrig mod occ
方案优势
- 规避
findImportedModule的两类问题:既不会因NoPkgQual返回未加载模块,也不会因单元依赖顺序触发panic - 使用GHC公开的单元状态查询API,完全合规,不依赖内部实现细节
- 逻辑清晰,仅在模块已加载时执行查找,符合你"仅在特定模块上下文执行操作"的需求
额外建议
如果插件仅需在模块存在时触发逻辑,也可以尝试findModule,但findModule可能触发模块加载流程,因此优先使用上述"先检查加载状态"的方式更稳妥。
内容的提问来源于stack exchange,提问作者Cactus
相关产品推荐
相关产品推荐

