summaryrefslogtreecommitdiff
path: root/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/template-haskell/Language/Haskell/TH/Syntax.hs')
-rw-r--r--libraries/template-haskell/Language/Haskell/TH/Syntax.hs69
1 files changed, 57 insertions, 12 deletions
diff --git a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
index b64dfffb93..97c379d407 100644
--- a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
+++ b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
@@ -38,6 +38,7 @@ import Data.Int
import Data.Word
import Data.Ratio
import GHC.Generics ( Generic )
+import GHC.Lexeme ( startsVarSym, startsVarId )
#ifdef HAS_NATURAL
import Numeric.Natural
@@ -645,10 +646,10 @@ dataToQa mkCon mkLit appCon antiQ t =
Nothing ->
case constrRep constr of
AlgConstr _ ->
- appCon (mkCon conName) conArgs
+ appCon (mkCon funOrConName) conArgs
where
- conName :: Name
- conName =
+ funOrConName :: Name
+ funOrConName =
case showConstr constr of
"(:)" -> Name (mkOccName ":")
(NameG DataName
@@ -662,13 +663,23 @@ dataToQa mkCon mkLit appCon antiQ t =
(NameG DataName
(mkPkgName "ghc-prim")
(mkModName "GHC.Tuple"))
- con -> mkNameG_d (tyConPackage tycon)
- (tyConModule tycon)
- con
+ -- It is possible for a Data instance to be defined such
+ -- that toConstr uses a Constr defined using a function,
+ -- not a data constructor. In such a case, we must take
+ -- care to build the Name using mkNameG_v (for values),
+ -- not mkNameG_d (for data constructors).
+ -- See Trac #10796.
+ fun@(x:_) | startsVarSym x || startsVarId x
+ -> mkNameG_v tyconPkg tyconMod fun
+ con -> mkNameG_d tyconPkg tyconMod con
where
tycon :: TyCon
tycon = (typeRepTyCon . typeOf) t
+ tyconPkg, tyconMod :: String
+ tyconPkg = tyConPackage tycon
+ tyconMod = tyConModule tycon
+
conArgs :: [Q q]
conArgs = gmapQ (dataToQa mkCon mkLit appCon antiQ) t
IntConstr n ->
@@ -691,8 +702,17 @@ dataToExpQ :: Data a
=> (forall b . Data b => b -> Maybe (Q Exp))
-> a
-> Q Exp
-dataToExpQ = dataToQa conE litE (foldl appE)
- where conE s = return (ConE s)
+dataToExpQ = dataToQa varOrConE litE (foldl appE)
+ where
+ -- Make sure that VarE is used if the Constr value relies on a
+ -- function underneath the surface (instead of a constructor).
+ -- See Trac #10796.
+ varOrConE s =
+ case nameSpace s of
+ Just VarName -> return (VarE s)
+ Just DataName -> return (ConE s)
+ _ -> fail $ "Can't construct an expression from name "
+ ++ showName s
appE x y = do { a <- x; b <- y; return (AppE a b)}
litE c = return (LitE c)
@@ -710,8 +730,13 @@ dataToPatQ :: Data a
-> Q Pat
dataToPatQ = dataToQa id litP conP
where litP l = return (LitP l)
- conP n ps = do ps' <- sequence ps
- return (ConP n ps')
+ conP n ps =
+ case nameSpace n of
+ Just DataName -> do
+ ps' <- sequence ps
+ return (ConP n ps')
+ _ -> fail $ "Can't construct a pattern from name "
+ ++ showName n
-----------------------------------------------------
-- Names and uniques
@@ -855,13 +880,13 @@ data NameFlavour
-- An original name (occurrences only, not binders)
-- Need the namespace too to be sure which
-- thing we are naming
- deriving ( Typeable, Data, Eq, Ord, Generic )
+ deriving ( Typeable, Data, Eq, Ord, Show, Generic )
data NameSpace = VarName -- ^ Variables
| DataName -- ^ Data constructors
| TcClsName -- ^ Type constructors and classes; Haskell has them
-- in the same name space for now.
- deriving( Eq, Ord, Data, Typeable, Generic )
+ deriving( Eq, Ord, Show, Data, Typeable, Generic )
type Uniq = Int
@@ -907,6 +932,26 @@ namePackage :: Name -> Maybe String
namePackage (Name _ (NameG _ p _)) = Just (pkgString p)
namePackage _ = Nothing
+-- | Returns whether a name represents an occurrence of a top-level variable
+-- ('VarName'), data constructor ('DataName'), type constructor, or type class
+-- ('TcClsName'). If we can't be sure, it returns 'Nothing'.
+--
+-- ==== __Examples__
+--
+-- >>> nameSpace 'Prelude.id
+-- Just VarName
+-- >>> nameSpace (mkName "id")
+-- Nothing -- only works for top-level variable names
+-- >>> nameSpace 'Data.Maybe.Just
+-- Just DataName
+-- >>> nameSpace ''Data.Maybe.Maybe
+-- Just TcClsName
+-- >>> nameSpace ''Data.Ord.Ord
+-- Just TcClsName
+nameSpace :: Name -> Maybe NameSpace
+nameSpace (Name _ (NameG ns _ _)) = Just ns
+nameSpace _ = Nothing
+
{- |
Generate a capturable name. Occurrences of such names will be
resolved according to the Haskell scoping rules at the occurrence