Skip to content

Commit

Permalink
Merge pull request #508 from konn/tactic-exclude-coercions
Browse files Browse the repository at this point in the history
Makes dictionary argument exclusion logic in Tactic plugin more robust
  • Loading branch information
jneira authored Nov 25, 2020
2 parents 56ff141 + 01110c8 commit cb9a38b
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 8 deletions.
32 changes: 25 additions & 7 deletions plugins/tactics/src/Ide/Plugin/Tactic/CodeGen.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import GHC.SourceGen.Binds
import GHC.SourceGen.Expr
import GHC.SourceGen.Overloaded
import GHC.SourceGen.Pat
import Ide.Plugin.Tactic.GHC
import Ide.Plugin.Tactic.Judgements
import Ide.Plugin.Tactic.Machinery
import Ide.Plugin.Tactic.Naming
Expand Down Expand Up @@ -120,13 +121,30 @@ unzipTrace l =


-- | Essentially same as 'dataConInstOrigArgTys' in GHC,
-- but we need some tweaks in GHC >= 8.8.
-- Since old 'dataConInstArgTys' seems working with >= 8.8,
-- we just filter out non-class types in the result.
dataConInstOrigArgTys' :: DataCon -> [Type] -> [Type]
dataConInstOrigArgTys' con ty =
let tys0 = dataConInstArgTys con ty
in filter (maybe True (not . isClassTyCon) . tyConAppTyCon_maybe) tys0
-- but only accepts universally quantified types as the second arguments
-- and automatically introduces existentials.
--
-- NOTE: The behaviour depends on GHC's 'dataConInstOrigArgTys'.
-- We need some tweaks if the compiler changes the implementation.
dataConInstOrigArgTys'
:: DataCon
-- ^ 'DataCon'structor
-> [Type]
-- ^ /Universally/ quantified type arguments to a result type.
-- It /MUST NOT/ contain any dictionaries, coercion and existentials.
--
-- For example, for @MkMyGADT :: b -> MyGADT a c@, we
-- must pass @[a, c]@ as this argument but not @b@, as @b@ is an existential.
-> [Type]
-- ^ Types of arguments to the DataCon with returned type is instantiated with the second argument.
dataConInstOrigArgTys' con uniTys =
let exvars = dataConExTys con
in dataConInstOrigArgTys con $
uniTys ++ fmap mkTyVarTy exvars
-- Rationale: At least in GHC <= 8.10, 'dataConInstOrigArgTys'
-- unifies the second argument with DataCon's universals followed by existentials.
-- If the definition of 'dataConInstOrigArgTys' changes,
-- this place must be changed accordingly.

------------------------------------------------------------------------------
-- | Combinator for performing case splitting, and running sub-rules on the
Expand Down
8 changes: 7 additions & 1 deletion plugins/tactics/src/Ide/Plugin/Tactic/GHC.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Control.Monad.State
import qualified Data.Map as M
import Data.Maybe (isJust)
import Data.Traversable
import qualified DataCon as DataCon
import Development.IDE.GHC.Compat
import Generics.SYB (mkT, everywhere)
import Ide.Plugin.Tactic.Types
Expand All @@ -20,7 +21,6 @@ import TysWiredIn (intTyCon, floatTyCon, doubleTyCon, charTyCon)
import Unique
import Var


tcTyVar_maybe :: Type -> Maybe Var
tcTyVar_maybe ty | Just ty' <- tcView ty = tcTyVar_maybe ty'
tcTyVar_maybe (CastTy ty _) = tcTyVar_maybe ty -- look through casts, as
Expand Down Expand Up @@ -148,3 +148,9 @@ getPatName (fromPatCompat -> p0) =
#endif
_ -> Nothing

dataConExTys :: DataCon -> [TyCoVar]
#if __GLASGOW_HASKELL__ >= 808
dataConExTys = DataCon.dataConExTyCoVars
#else
dataConExTys = DataCon.dataConExTyVars
#endif
1 change: 1 addition & 0 deletions test/functional/Tactic.hs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ tests = testGroup
, goldenTest "GoldenSwap.hs" 2 8 Auto ""
, goldenTest "GoldenFmapTree.hs" 4 11 Auto ""
, goldenTest "GoldenGADTDestruct.hs" 7 17 Destruct "gadt"
, goldenTest "GoldenGADTDestructCoercion.hs" 8 17 Destruct "gadt"
, goldenTest "GoldenGADTAuto.hs" 7 13 Auto ""
, goldenTest "GoldenSwapMany.hs" 2 12 Auto ""
, goldenTest "GoldenBigTuple.hs" 4 12 Auto ""
Expand Down
8 changes: 8 additions & 0 deletions test/testdata/tactic/GoldenGADTDestructCoercion.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE GADTs #-}
module GoldenGADTDestruct where
data E a b where
E :: forall a b. (b ~ a, Ord a) => b -> E a [a]

ctxGADT :: E a b -> String
ctxGADT gadt = _decons
8 changes: 8 additions & 0 deletions test/testdata/tactic/GoldenGADTDestructCoercion.hs.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE GADTs #-}
module GoldenGADTDestruct where
data E a b where
E :: forall a b. (b ~ a, Ord a) => b -> E a [a]

ctxGADT :: E a b -> String
ctxGADT gadt = (case gadt of { (E b) -> _ })

0 comments on commit cb9a38b

Please sign in to comment.