hpgsql-0.3.0: src/Hpgsql/LanguageHaskell/ParseHaskellExpression.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE PackageImports #-}
{- FOURMOLU_DISABLE -} -- CPP macros make fourmolu fail
module Hpgsql.LanguageHaskell.ParseHaskellExpression (parseHaskellExpression, isValidHaskellExpression) where
import Data.Char (isUpper)
import Data.Either (isRight)
import qualified Data.List as List
import Data.Foldable (toList)
import Data.Maybe (mapMaybe)
import GHC.Data.FastString (mkFastString, unpackFS)
import GHC.Data.StringBuffer (stringToStringBuffer)
import GHC.Driver.Config.Parser (initParserOpts)
import GHC.Driver.Session (DynFlags, defaultDynFlags, xopt_set)
import GHC.Hs (GhcPs)
import GHC.Parser (parseExpression)
import GHC.Parser.Lexer (P (..), ParseResult (..), initParserState)
import GHC.Parser.PostProcess (ECP (..), runPV)
import GHC.Types.Basic (Boxity (..))
import GHC.Types.Name (nameOccName)
import GHC.Types.Name.Occurrence (occNameString)
import GHC.Types.Name.Reader (RdrName (..))
import GHC.Types.SourceText (IntegralLit (..), rationalFromFractionalLit)
import GHC.Types.SrcLoc (GenLocated (..), mkRealSrcLoc)
import Hpgsql.LanguageHaskell.GhcParserOpts (fakeSettings)
import Hpgsql.LanguageHaskell.FromThExtension (fromThToGhcLibExtension)
import Language.Haskell.Syntax (FieldOcc (..), GRHS (..), GRHSs (..), HsBindLR (..), HsConDetails (..), HsConPatDetails, HsFieldBind (..), HsLit (..), HsLocalBinds, HsLocalBindsLR (..), HsOverLit (..), HsRecFields (..), HsSigType (..), HsTupArg (..), HsType (..), HsValBindsLR (..), HsWildCardBndrs (..), LHsExpr, LHsRecField, LHsSigWcType, LMatch, LPat, Match (..), MatchGroup (..), OverLitVal (..), Pat (..), PromotionFlag (..))
import Language.Haskell.Syntax.Basic (FieldLabelString (..))
import Language.Haskell.Syntax.Expr (DotFieldOcc (..), HsExpr (..))
import Language.Haskell.Syntax.Module.Name (moduleNameString)
import qualified "template-haskell" Language.Haskell.TH as TH
-- | Parse a Haskell expression string into a Template Haskell Exp.
parseHaskellExpression :: [TH.Extension] -> String -> Either String TH.Exp
parseHaskellExpression callerExtensions str = do
hsExpr <- ghcParse callerExtensions str
convertExpr hsExpr
-- | Check if a string can be parsed as a Haskell expression.
isValidHaskellExpression :: [TH.Extension] -> String -> Bool
-- NOTE: This uses `ghcParse` instead of `parseHaskellExpression` on purpose.
-- The reasoning is if we find a valid Haskell expression inside
-- a quasiquoter, we want to parse it as a Haskell expression.
-- If later on we don't support converting that to template-haskell,
-- that's hpgsql's limitation and we want a good error to be thrown
-- to the user, which `parseHaskellExpression` will do.
-- And we don't want to mislead our quasiquoter parser into skipping
-- a valid Haskell expression inside #{} or ^{} just because hpgsql
-- can't convert it to TH: best to fail loud and clear.
isValidHaskellExpression callerExtensions = isRight . ghcParse callerExtensions
ghcParse :: [TH.Extension] -> String -> Either String (HsExpr GhcPs)
ghcParse callerExtensions str =
let buf = stringToStringBuffer str
loc = mkRealSrcLoc (mkFastString "<hpgsql>") 1 1
opts = initParserOpts parserDynFlags
parseExprP = parseExpression >>= \ecp -> runPV (unECP ecp)
in case unP parseExprP (initParserState opts buf loc) of
POk _ (L _ expr) -> Right expr
PFailed _ -> Left "Failed to parse Haskell expression"
where
parserDynFlags :: DynFlags
parserDynFlags =
List.foldl'
xopt_set
(defaultDynFlags fakeSettings)
(mapMaybe fromThToGhcLibExtension callerExtensions)
--
-- GHC HsExpr to TH Exp conversion
convertExpr :: HsExpr GhcPs -> Either String TH.Exp
convertExpr (HsVar _ (L _ rdr)) = Right (rdrToExp rdr)
convertExpr (HsApp _ (L _ f) (L _ x)) = TH.AppE <$> convertExpr f <*> convertExpr x
convertExpr (OpApp _ (L _ l) (L _ op) (L _ r)) = do
l' <- convertExpr l
op' <- convertExpr op
r' <- convertExpr r
Right (TH.UInfixE l' op' r')
convertExpr (NegApp _ (L _ e) _) = do
e' <- convertExpr e
Right $ TH.AppE (TH.VarE 'negate) e'
#if MIN_VERSION_ghc_lib_parser(9,10,0)
convertExpr (HsPar _ (L _ e)) = TH.ParensE <$> convertExpr e
#elif MIN_VERSION_ghc_lib_parser(9,8,0)
convertExpr (HsPar _ _ (L _ e) _) = TH.ParensE <$> convertExpr e
#endif
convertExpr (ExplicitList _ es) = TH.ListE <$> traverse (\(L _ e) -> convertExpr e) es
convertExpr (ExplicitTuple _ args boxity) = do
args' <- traverse convertTupArg args
Right
( case boxity of
Boxed -> TH.TupE args'
Unboxed -> TH.UnboxedTupE args'
)
convertExpr (SectionL _ (L _ e) (L _ op)) = do
e' <- convertExpr e
op' <- convertExpr op
Right (TH.InfixE (Just e') op' Nothing)
convertExpr (SectionR _ (L _ op) (L _ e)) = do
op' <- convertExpr op
e' <- convertExpr e
Right (TH.InfixE Nothing op' (Just e'))
convertExpr (HsIf _ (L _ c) (L _ t) (L _ f)) = do
c' <- convertExpr c
t' <- convertExpr t
f' <- convertExpr f
Right (TH.CondE c' t' f')
convertExpr (HsLit _ lit) = TH.LitE <$> convertHsLit lit
convertExpr (HsOverLit _ ol) = TH.LitE <$> convertOverLit ol
convertExpr (ExprWithTySig _ (L _ e) sigWcTy) = do
e' <- convertExpr e
ty' <- convertSigWcType sigWcTy
Right (TH.SigE e' ty')
convertExpr (HsGetField _ (L _ e) (L _ (DotFieldOcc _ (L _ fld)))) = do
e' <- convertExpr e
Right (TH.GetFieldE e' (fieldLabelToString fld))
#if MIN_VERSION_ghc_lib_parser(9,10,0)
convertExpr (HsProjection _ flds) =
Right (TH.ProjectionE (fmap (\(DotFieldOcc _ (L _ fld)) -> fieldLabelToString fld) flds))
#elif MIN_VERSION_ghc_lib_parser(9,8,0)
convertExpr (HsProjection _ flds) =
Right (TH.ProjectionE (fmap (\(L _ (DotFieldOcc _ (L _ fld))) -> fieldLabelToString fld) flds))
#endif
#if MIN_VERSION_ghc_lib_parser(9,10,0)
convertExpr (HsAppType _ (L _ e) (HsWC _ (L _ ty))) = TH.AppTypeE <$> convertExpr e <*> convertType ty
#else
convertExpr (HsAppType _ (L _ e) _ (HsWC _ (L _ ty))) = TH.AppTypeE <$> convertExpr e <*> convertType ty
#endif
#if MIN_VERSION_ghc_lib_parser(9,10,0)
convertExpr (RecordCon _ (L _ conName) (HsRecFields _ flds _)) = do
flds' <- traverse convertRecField flds
Right $ TH.RecConE (rdrToName conName) flds'
#elif MIN_VERSION_ghc_lib_parser(9,8,0)
convertExpr (RecordCon _ (L _ conName) (HsRecFields flds _)) = do
flds' <- traverse convertRecField flds
Right $ TH.RecConE (rdrToName conName) flds'
#endif
convertExpr (HsCase _ (L _ caseExpr) mg) = TH.CaseE <$> convertExpr caseExpr <*> convertMatchGroup mg
#if MIN_VERSION_ghc_lib_parser(9,10,0)
convertExpr (HsLet _ localBinds (L _ body)) = do
#else
convertExpr (HsLet _ _ localBinds _ (L _ body)) = do
#endif
decs <- convertLocalBinds localBinds
body' <- convertExpr body
Right (TH.LetE decs body')
-- Now come our list of unsupported language features
#if MIN_VERSION_ghc_lib_parser(9,10,0)
convertExpr (HsEmbTy {}) = unsupportedLanguageFeatureMsg "Embedded type"
convertExpr (HsForAll {}) = unsupportedLanguageFeatureMsg "Forall-types"
convertExpr (HsFunArr {}) = unsupportedLanguageFeatureMsg "Function types"
convertExpr (HsQual {}) = unsupportedLanguageFeatureMsg "HsQual"
#else
convertExpr (HsLamCase {}) = unsupportedLanguageFeatureMsg "LambdaCase"
convertExpr (HsRecSel {}) = unsupportedLanguageFeatureMsg "Record field selectors"
#endif
convertExpr (HsUnboundVar {}) = unsupportedLanguageFeatureMsg "Unbound variables/holes"
convertExpr (HsOverLabel {}) = unsupportedLanguageFeatureMsg "Overloaded labels"
convertExpr (HsIPVar {}) = unsupportedLanguageFeatureMsg "Implicit parameters"
convertExpr (HsLam {}) = unsupportedLanguageFeatureMsg "Lambda"
convertExpr (ExplicitSum {}) = unsupportedLanguageFeatureMsg "Unboxed sums"
convertExpr (HsMultiIf {}) = unsupportedLanguageFeatureMsg "Multi-way if"
convertExpr (HsDo {}) = unsupportedLanguageFeatureMsg "Do notation"
convertExpr (RecordUpd {}) = unsupportedLanguageFeatureMsg "Record updates"
convertExpr (ArithSeq {}) = unsupportedLanguageFeatureMsg "Arithmetic sequences"
convertExpr (HsTypedBracket {}) = unsupportedLanguageFeatureMsg "Typed Template Haskell brackets"
convertExpr (HsUntypedBracket {}) = unsupportedLanguageFeatureMsg "Untyped Template Haskell brackets"
convertExpr (HsTypedSplice {}) = unsupportedLanguageFeatureMsg "Typed Template Haskell splices"
convertExpr (HsUntypedSplice {}) = unsupportedLanguageFeatureMsg "Untyped Template Haskell splices"
convertExpr (HsProc {}) = unsupportedLanguageFeatureMsg "Arrow proc notation"
convertExpr (HsStatic {}) = unsupportedLanguageFeatureMsg "Static pointers"
convertExpr (HsPragE {}) = unsupportedLanguageFeatureMsg "Pragma"
unsupportedLanguageFeatureMsg :: String -> Either String a
unsupportedLanguageFeatureMsg feat = Left $ feat ++ " expressions are unsupported in hpgsql's SQL quasi-quoter. You can usually assign your expression to a binding outside the quasi-quoter and keep only that binding inside, but do raise an issue at https://github.com/mzabani/hpgsql/issues if you want this to be supported."
convertMatchGroup :: MatchGroup GhcPs (LHsExpr GhcPs) -> Either String [TH.Match]
convertMatchGroup (MG _ (L _ matches)) = traverse convertMatch matches
convertMatch :: LMatch GhcPs (LHsExpr GhcPs) -> Either String TH.Match
#if MIN_VERSION_ghc_lib_parser(9,10,0)
convertMatch (L _ (Match _ _ (L _ pats) grhss)) = do
#else
convertMatch (L _ (Match _ _ pats grhss)) = do
#endif
pats' <- traverse (\(L _ p) -> convertPat p) pats
(body, decs) <- convertGRHSs grhss
case pats' of
[pat] -> Right (TH.Match pat body decs)
_ -> unsupportedLanguageFeatureMsg "Multi-pattern matches"
convertGRHSs :: GRHSs GhcPs (LHsExpr GhcPs) -> Either String (TH.Body, [TH.Dec])
convertGRHSs (GRHSs _ grhss localBinds) = do
decs <- convertLocalBinds localBinds
body <- case grhss of
[L _ (GRHS _ [] (L _ e))] -> TH.NormalB <$> convertExpr e
_ -> unsupportedLanguageFeatureMsg "Guarded case alternative"
Right (body, decs)
convertLocalBinds :: HsLocalBinds GhcPs -> Either String [TH.Dec]
convertLocalBinds (EmptyLocalBinds _) = Right []
convertLocalBinds (HsValBinds _ (ValBinds _ binds _sigs)) =
traverse (\(L _ b) -> convertBind b) (toList binds)
convertLocalBinds (HsValBinds _ (XValBindsLR {})) =
unsupportedLanguageFeatureMsg "XValBindsLR"
convertLocalBinds (HsIPBinds {}) = unsupportedLanguageFeatureMsg "HsIPBinds"
convertBind :: HsBindLR GhcPs GhcPs -> Either String TH.Dec
convertBind FunBind { fun_id = L _ name, fun_matches = MG _ (L _ matches) } = do
clauses <- traverse convertClause matches
Right (TH.FunD (rdrToName name) clauses)
convertBind PatBind { pat_lhs = L _ pat, pat_rhs = grhss } = do
pat' <- convertPat pat
(body, decs) <- convertGRHSs grhss
Right (TH.ValD pat' body decs)
convertBind (VarBind{}) = unsupportedLanguageFeatureMsg "VarBind"
convertBind (PatSynBind{}) = unsupportedLanguageFeatureMsg "Pattern Synonyms bindings"
convertClause :: LMatch GhcPs (LHsExpr GhcPs) -> Either String TH.Clause
#if MIN_VERSION_ghc_lib_parser(9,10,0)
convertClause (L _ (Match _ _ (L _ pats) grhss)) = do
#else
convertClause (L _ (Match _ _ pats grhss)) = do
#endif
pats' <- traverse (\(L _ p) -> convertPat p) pats
(body, decs) <- convertGRHSs grhss
Right (TH.Clause pats' body decs)
-- Pattern conversion (GHC Pat to TH Pat)
convertPat :: Pat GhcPs -> Either String TH.Pat
convertPat (WildPat _) = Right TH.WildP
convertPat (VarPat _ (L _ rdr)) = Right (TH.VarP (rdrToName rdr))
convertPat (LitPat _ lit) = TH.LitP <$> convertHsLit lit
convertPat (NPat _ (L _ ol) _ _) = TH.LitP <$> convertOverLit ol
#if MIN_VERSION_ghc_lib_parser(9,10,0)
convertPat (ConPat _ (L _ con) details) = convertConPatDetails con details
#elif MIN_VERSION_ghc_lib_parser(9,8,0)
convertPat (ConPat _ (L _ con) details) = convertConPatDetails con details
#endif
convertPat (TuplePat _ pats boxity) = do
pats' <- traverse (\(L _ p) -> convertPat p) pats
Right $ case boxity of
Boxed -> TH.TupP pats'
Unboxed -> TH.UnboxedTupP pats'
convertPat (ListPat _ pats) = TH.ListP <$> traverse (\(L _ p) -> convertPat p) pats
#if MIN_VERSION_ghc_lib_parser(9,10,0)
convertPat (ParPat _ (L _ p)) = TH.ParensP <$> convertPat p
convertPat (AsPat _ (L _ rdr) (L _ p)) = TH.AsP (rdrToName rdr) <$> convertPat p
#elif MIN_VERSION_ghc_lib_parser(9,8,0)
convertPat (ParPat _ _ (L _ p) _) = TH.ParensP <$> convertPat p
convertPat (AsPat _ (L _ rdr) _ (L _ p)) = TH.AsP (rdrToName rdr) <$> convertPat p
#endif
convertPat (BangPat _ (L _ p)) = TH.BangP <$> convertPat p
-- Unsupported pattern matching expressions
convertPat (LazyPat{}) = unsupportedLanguageFeatureMsg "LazyPat in pattern matching"
convertPat (ViewPat{}) = unsupportedLanguageFeatureMsg "ViewPat in pattern matching"
convertPat (SumPat{}) = unsupportedLanguageFeatureMsg "SumPat in pattern matching"
convertPat (SplicePat{}) = unsupportedLanguageFeatureMsg "SplicePat in pattern matching"
convertPat (SigPat{}) = unsupportedLanguageFeatureMsg "SigPat in pattern matching"
convertPat (NPlusKPat{}) = unsupportedLanguageFeatureMsg "NPlusKPat in pattern matching"
#if MIN_VERSION_ghc_lib_parser(9,10,0)
convertPat (EmbTyPat{}) = unsupportedLanguageFeatureMsg "EmbTyPat in pattern matching"
convertPat (InvisPat{}) = unsupportedLanguageFeatureMsg "InvisPat in pattern matching"
convertPat (OrPat{}) = unsupportedLanguageFeatureMsg "OrPat in pattern matching"
#endif
convertConPatDetails :: RdrName -> HsConPatDetails GhcPs -> Either String TH.Pat
convertConPatDetails con (PrefixCon tyArgs args) = do
args' <- traverse (\(L _ p) -> convertPat p) args
if null tyArgs
then Right (TH.ConP (rdrToName con) [] args')
else unsupportedLanguageFeatureMsg "Type applications in constructor patterns"
convertConPatDetails con (InfixCon (L _ l) (L _ r)) = do
l' <- convertPat l
r' <- convertPat r
Right (TH.InfixP l' (rdrToName con) r')
#if MIN_VERSION_ghc_lib_parser(9,10,0)
convertConPatDetails con (RecCon (HsRecFields _ flds _)) = do
flds' <- traverse convertPatRecField flds
Right (TH.RecP (rdrToName con) flds')
#elif MIN_VERSION_ghc_lib_parser(9,8,0)
convertConPatDetails con (RecCon (HsRecFields flds _)) = do
flds' <- traverse convertPatRecField flds
Right (TH.RecP (rdrToName con) flds')
#endif
convertPatRecField :: LHsRecField GhcPs (LPat GhcPs) -> Either String TH.FieldPat
convertPatRecField (L _ (HsFieldBind _ (L _ (FieldOcc _ (L _ rdr))) (L _ pat) _)) = do
pat' <- convertPat pat
Right (rdrToName rdr, pat')
-- Helper functions
rdrToExp :: RdrName -> TH.Exp
rdrToExp rdr =
let name = rdrToName rdr
in if isConstructorName name then TH.ConE name else TH.VarE name
rdrToName :: RdrName -> TH.Name
rdrToName (Unqual occ) = TH.mkName (occNameString occ)
rdrToName (Qual modN occ) = TH.mkName (moduleNameString modN ++ "." ++ occNameString occ)
rdrToName (Orig _ occ) = TH.mkName (occNameString occ)
rdrToName (Exact name) = TH.mkName (occNameString (nameOccName name))
isConstructorName :: TH.Name -> Bool
isConstructorName n = case TH.nameBase n of
(c : _) -> isUpper c || c == ':'
_ -> False
fieldLabelToString :: FieldLabelString -> String
fieldLabelToString (FieldLabelString fs) = unpackFS fs
convertRecField :: LHsRecField GhcPs (LHsExpr GhcPs) -> Either String (TH.Name, TH.Exp)
convertRecField (L _ (HsFieldBind _ (L _ (FieldOcc _ (L _ rdr))) (L _ expr) _)) = do
expr' <- convertExpr expr
Right (rdrToName rdr, expr')
convertTupArg :: HsTupArg GhcPs -> Either String (Maybe TH.Exp)
convertTupArg (Present _ (L _ e)) = Just <$> convertExpr e
convertTupArg (Missing _) = Right Nothing
convertHsLit :: HsLit GhcPs -> Either String TH.Lit
convertHsLit (HsChar _ c) = Right (TH.CharL c)
convertHsLit (HsString _ fs) = Right (TH.StringL (unpackFS fs))
convertHsLit (HsInt _ il) = Right (TH.IntegerL (il_value il))
convertHsLit (HsIntPrim _ i) = Right (TH.IntPrimL i)
convertHsLit (HsWordPrim _ w) = Right (TH.WordPrimL w)
convertHsLit (HsFloatPrim _ fl) = Right (TH.FloatPrimL (rationalFromFractionalLit fl))
convertHsLit (HsDoublePrim _ fl) = Right (TH.DoublePrimL (rationalFromFractionalLit fl))
#if MIN_VERSION_ghc_lib_parser(9,10,0)
convertHsLit (HsMultilineString _ fs) = Right (TH.StringL (unpackFS fs))
#endif
convertHsLit (HsCharPrim {}) = unsupportedLanguageFeatureMsg "HsCharPrim literal"
convertHsLit (HsStringPrim {}) = unsupportedLanguageFeatureMsg "HsStringPrim literal"
convertHsLit (HsInt8Prim {}) = unsupportedLanguageFeatureMsg "HsInt8Prim literal"
convertHsLit (HsInt16Prim {}) = unsupportedLanguageFeatureMsg "HsInt16Prim literal"
convertHsLit (HsInt32Prim {}) = unsupportedLanguageFeatureMsg "HsInt32Prim literal"
convertHsLit (HsInt64Prim {}) = unsupportedLanguageFeatureMsg "HsInt64Prim literal"
convertHsLit (HsWord8Prim {}) = unsupportedLanguageFeatureMsg "HsWord8Prim literal"
convertHsLit (HsWord16Prim {}) = unsupportedLanguageFeatureMsg "HsWord16Prim literal"
convertHsLit (HsWord32Prim {}) = unsupportedLanguageFeatureMsg "HsWord32Prim literal"
convertHsLit (HsWord64Prim {}) = unsupportedLanguageFeatureMsg "HsWord64Prim literal"
convertHsLit (HsInteger {}) = unsupportedLanguageFeatureMsg "HsInteger literal"
convertHsLit (HsRat {}) = unsupportedLanguageFeatureMsg "HsRat literal"
convertOverLit :: HsOverLit GhcPs -> Either String TH.Lit
convertOverLit ol = case ol_val ol of
HsIntegral il -> Right (TH.IntegerL (il_value il))
HsFractional fl -> Right (TH.RationalL (rationalFromFractionalLit fl))
HsIsString _ fs -> Right (TH.StringL (unpackFS fs))
-- Type conversion (GHC HsType to TH Type)
convertSigWcType :: LHsSigWcType GhcPs -> Either String TH.Type
convertSigWcType (HsWC _ (L _ (HsSig _ _ (L _ ty)))) = convertType ty
convertType :: HsType GhcPs -> Either String TH.Type
convertType (HsTyVar _ promo (L _ rdr)) =
let name = rdrToName rdr
in Right $ case promo of
IsPromoted -> TH.PromotedT name
NotPromoted
| isConstructorName name -> TH.ConT name
| otherwise -> TH.VarT name
convertType (HsAppTy _ (L _ t1) (L _ t2)) =
TH.AppT <$> convertType t1 <*> convertType t2
convertType (HsListTy _ (L _ t)) =
TH.AppT TH.ListT <$> convertType t
convertType (HsTupleTy _ _ ts) = do
ts' <- traverse (\(L _ t) -> convertType t) ts
let n = length ts'
Right (foldl TH.AppT (TH.TupleT n) ts')
convertType (HsFunTy _ _ (L _ t1) (L _ t2)) =
TH.AppT . TH.AppT TH.ArrowT <$> convertType t1 <*> convertType t2
convertType (HsParTy _ (L _ t)) =
convertType t
convertType (HsQualTy _ _ (L _ t)) =
convertType t
convertType (HsForAllTy{}) = unsupportedLanguageFeatureMsg "HsForAllTy in a type"
convertType (HsAppKindTy{}) = unsupportedLanguageFeatureMsg "HsAppKindTy in a type"
convertType (HsOpTy{}) = unsupportedLanguageFeatureMsg "HsOpTy in a type"
convertType (HsSumTy{}) = unsupportedLanguageFeatureMsg "HsSumTy in a type"
convertType (HsIParamTy{}) = unsupportedLanguageFeatureMsg "HsIParamTy in a type"
convertType (HsStarTy{}) = unsupportedLanguageFeatureMsg "HsStarTy in a type"
convertType (HsKindSig{}) = unsupportedLanguageFeatureMsg "HsKindSig in a type"
convertType (HsSpliceTy{}) = unsupportedLanguageFeatureMsg "HsSpliceTy in a type"
convertType (HsDocTy{}) = unsupportedLanguageFeatureMsg "HsDocTy in a type"
convertType (HsBangTy{}) = unsupportedLanguageFeatureMsg "HsBangTy in a type"
convertType (HsRecTy{}) = unsupportedLanguageFeatureMsg "HsRecTy in a type"
convertType (HsExplicitListTy{}) = unsupportedLanguageFeatureMsg "HsExplicitListTy in a type"
convertType (HsExplicitTupleTy{}) = unsupportedLanguageFeatureMsg "HsExplicitTupleTy in a type"
convertType (HsTyLit{}) = unsupportedLanguageFeatureMsg "HsTyLit in a type"
convertType (HsWildCardTy{}) = unsupportedLanguageFeatureMsg "HsWildCardTy in a type"
convertType (XHsType{}) = unsupportedLanguageFeatureMsg "XHsType in a type"