+Note [tagToEnum#]
+~~~~~~~~~~~~~~~~~
+Nasty check to ensure that tagToEnum# is applied to a type that is an
+enumeration TyCon. Unification may refine the type later, but this
+check won't see that, alas. It's crude but it works.
+
+Here's are two cases that should fail
+ f :: forall a. a
+ f = tagToEnum# 0 -- Can't do tagToEnum# at a type variable
+
+ g :: Int
+ g = tagToEnum# 0 -- Int is not an enumeration
+
+
+\begin{code}
+doStupidChecks :: HsExpr TcId
+ -> [([TcType], ThetaType)]
+ -> TcM ()
+-- Check two tiresome and ad-hoc cases
+-- (a) the "stupid theta" for a data con; add the constraints
+-- from the "stupid theta" of a data constructor (sigh)
+-- (b) deal with the tagToEnum# problem: see Note [tagToEnum#]
+
+doStupidChecks (HsVar fun_id) ((tys,_):_)
+ | Just con <- isDataConId_maybe fun_id -- (a)
+ = addDataConStupidTheta con tys
+
+ | fun_id `hasKey` tagToEnumKey -- (b)
+ = do { tys' <- zonkTcTypes tys
+ ; checkTc (ok tys') (tagToEnumError tys')
+ }
+ where
+ ok [] = False
+ ok (ty:tys) = case tcSplitTyConApp_maybe ty of
+ Just (tc,_) -> isEnumerationTyCon tc
+ Nothing -> False
+
+doStupidChecks fun tv_theta_prs
+ = return () -- The common case
+
+
+tagToEnumError tys
+ = hang (ptext SLIT("Bad call to tagToEnum#") <+> at_type)
+ 2 (vcat [ptext SLIT("Specify the type by giving a type signature"),
+ ptext SLIT("e.g. (tagToEnum# x) :: Bool")])
+ where
+ at_type | null tys = empty -- Probably never happens
+ | otherwise = ptext SLIT("at type") <+> ppr (head tys)
+\end{code}
+