Skip to content

Impove Lint check for empty cases

The Lint check for empty case alternative looks wonky to me

     ; case tyConAppTyCon_maybe (idType var) of
         Just tycon
              | debugIsOn
              , isAlgTyCon tycon
              , not (isAbstractTyCon tycon)
              , null (tyConDataCons tycon)
              , not (exprIsDeadEnd scrut)
              -> pprTrace "Lint warning: case binder's type has no constructors" (ppr var <+> ppr (idType var))
                        -- This can legitimately happen for type families
                      $ return ()
         _otherwise -> return ()

For example

   data T a = T1 !(F a) | T2 Int
   data DataConCantHappen -- No constructors
   type instance F Bool = DataConCantHappen

   f (x::T Bool) = case x of
                     T1 v -> case (v |> co) of {}
                     T2 x -> blah

   where co :: F Bool ~ Void

Here the T1 alternative in f's RHS is in fact inaccessible: T1 is a strict constructor and there are no inhabitants of (F Bool), which is equal to DataConCantHappen. GHC itself uses this a lot in HsSyn to make inactive constructors inaccessible.

So there is no hope of being sure that the scrutinee is bottoming -- except via its type. And in this test we've already checked for empty data cons.

I think we need something more like

     ; checkL (not (null alts) || exprIsDeadEnd scrut) $
       hang (text "Illegal empty case")
          2 (ppr case_bndr <+> ppr case_bndr_ty $$ ppr e)

where exprIsDeadEnd checks for empty types (which it already does, more or less).

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