{-# OPTIONS_GHC -Wincomplete-patterns -fforce-recomp #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE BangPatterns #-}
module Lib where

import Data.Void

strictConst :: a -> b -> a
strictConst a b = seq b a

pattern F  <- (const       False -> True)
pattern SF <- (strictConst False -> True)

-- | The second clause is redundant, really, because (the matcher of) 'F' is
-- not strict in its argument. As a result, the third clause is *not*
-- redundant, but inaccessible RHS! Deleting the third clause would be unsound.
-- This is bad, especially because this outcome depends entirely on the
-- strictness of 'F's matcher.
f :: Bool -> Bool -> ()
f _  True = ()
f F  True = ()
f !_ True = ()
f _  _    = ()

-- | In this example, the second clause really is inaccessible RHS (because SF
-- is a strict match). And as a result, the third clause *is* redundant.
f2 :: Bool -> Bool -> ()
f2 _  True = ()
f2 SF True = ()
f2 !_ True = ()
f2 _  _    = ()

pattern T <- (const True -> True)
{-# COMPLETE T, F :: Void #-}

-- | But we consider COMPLETE signatures to cover bottom. Hence the last clause
-- here should be redunant, not inaccessible RHS.
f3 :: Void -> ()
f3 T  = ()
f3 F  = ()
f3 !_ = ()

-- The following is related to the same issue:

-- | The following function definition is exhaustive.
-- Its clauses are *not* inaccessible RHS, because neither
-- pattern synonym is strict.
g :: Void -> ()
g F = ()
g T = ()
