Skip to content

GHC reports an exact Name is not in scope when quoting ANN

If you compile the following program:

{-# LANGUAGE TemplateHaskell #-}
module Bug where

$([d| x :: Int
      x = 42
      {-# ANN x "blah" #-}
    |])

You'll get:

$ /opt/ghc/8.10.3/bin/ghc Bug.hs
[1 of 1] Compiling Bug              ( Bug.hs, Bug.o, Bug.dyn_o )

Bug.hs:4:3: error:
    • The exact Name ‘x’ is not in scope
        Probable cause: you used a unique Template Haskell name (NameU), 
        perhaps via newName, but did not bind it
        If that's it, then -ddump-splices might be useful
    • In the annotation: {-# ANN x "blah" #-}
  |
4 | $([d| x :: Int
  |   ^^^^^^^^^^^^...

Which probably shouldn't happen. If you compile with -ddump-splices, it's more obvious what is happening:

Bug.hs:(4,3)-(7,6): Splicing declarations
    [d| {-# ANN x_age "blah" #-}
        
        x_age :: Int
        x_age = 42 |]
  ======>
    x_a25M :: Int
    x_a25M = 42
    {-# ANN x_age "blah" #-}

The name mentioned in the ANN (x_age) is not the same name mentioned in the function declaration (x_a25M). As for why this happens, I believe this code is responsible:

repAnnProv :: AnnProvenance Name -> MetaM (Core TH.AnnTarget)
repAnnProv (ValueAnnProvenance (L _ n))
  = do { MkC n' <- lift $ globalVar n  -- ANNs are allowed only at top-level
       ; rep2_nw valueAnnotationName [ n' ] }
repAnnProv (TypeAnnProvenance (L _ n))
  = do { MkC n' <- lift $ globalVar n
       ; rep2_nw typeAnnotationName [ n' ] }
repAnnProv ModuleAnnProvenance
  = rep2_nw moduleAnnotationName []

This turns the Core Name inside an ANN to a Template Haskell Name by way of globalVar, which allocates a fresh Template Haskell Name regardless of what other Names are in scope. I think that globalVar should actually be lookupLOcc instead. Indeed, this patch appears to fix the issue locally:

diff --git a/compiler/GHC/HsToCore/Quote.hs b/compiler/GHC/HsToCore/Quote.hs
index 767914127a..a6e1100419 100644
--- a/compiler/GHC/HsToCore/Quote.hs
+++ b/compiler/GHC/HsToCore/Quote.hs
@@ -848,11 +848,11 @@ repAnnD (L loc (HsAnnotation _ _ ann_prov (L _ exp)))
        ; return (loc, dec) }
 
 repAnnProv :: AnnProvenance Name -> MetaM (Core TH.AnnTarget)
-repAnnProv (ValueAnnProvenance (L _ n))
-  = do { MkC n' <- lift $ globalVar n  -- ANNs are allowed only at top-level
+repAnnProv (ValueAnnProvenance n)
+  = do { MkC n' <- lookupLOcc n  -- ANNs are allowed only at top-level
        ; rep2_nw valueAnnotationName [ n' ] }
-repAnnProv (TypeAnnProvenance (L _ n))
-  = do { MkC n' <- lift $ globalVar n
+repAnnProv (TypeAnnProvenance n)
+  = do { MkC n' <- lookupLOcc n
        ; rep2_nw typeAnnotationName [ n' ] }
 repAnnProv ModuleAnnProvenance
   = rep2_nw moduleAnnotationName []

The comment says "ANNs are allowed only at top-level", but I don't think that's relevant here. After all, standalone kind signatures are also allowed only at the top level, but repKiSigD still uses lookupLOcc.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information