summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2012-06-13 17:21:09 +0100
committerSimon Peyton Jones <simonpj@microsoft.com>2012-06-13 17:21:09 +0100
commit5a8ac0f823c151c062a3f1903574030423bb255c (patch)
tree60c7bbe1091ddba9c404f8024928fcea83480523
parent03f78f0686f048e75d671f2797c8684b71655c49 (diff)
downloadhaskell-5a8ac0f823c151c062a3f1903574030423bb255c.tar.gz
Simplify the implementation of Implicit Parameters
This patch re-implements implicit parameters via a class with a functional dependency: class IP (n::Symbol) a | n -> a where ip :: a This definition is in the library module GHC.IP. Notice how it use a type-literal, so we can have constraints like IP "x" Int Now all the functional dependency machinery works right to make implicit parameters behave as they should. Much special-case processing for implicit parameters can be removed entirely. One particularly nice thing is not having a dedicated "original-name cache" for implicit parameters (the nsNames field of NameCache). But many other cases disappear: * BasicTypes.IPName * IPTyCon constructor in Tycon.TyCon * CIPCan constructor in TcRnTypes.Ct * IPPred constructor in Types.PredTree Implicit parameters remain special in a few ways: * Special syntax. Eg the constraint (IP "x" Int) is parsed and printed as (?x::Int). And we still have local bindings for implicit parameters, and occurrences thereof. * A implicit-parameter binding (let ?x = True in e) amounts to a local instance declaration, which we have not had before. It just generates an implication contraint (easy), but when going under it we must purge any existing bindings for ?x in the inert set. See Note [Shadowing of Implicit Parameters] in TcSimplify * TcMType.sizePred classifies implicit parameter constraints as size-0, as before the change There are accompanying patches to libraries 'base' and 'haddock' All the work was done by Iavor Diatchki
-rw-r--r--compiler/basicTypes/BasicTypes.lhs28
-rw-r--r--compiler/basicTypes/Unique.lhs3
-rw-r--r--compiler/coreSyn/MkCore.lhs23
-rw-r--r--compiler/deSugar/DsExpr.lhs6
-rw-r--r--compiler/ghc.cabal.in1
-rw-r--r--compiler/hsSyn/HsBinds.lhs13
-rw-r--r--compiler/hsSyn/HsExpr.lhs2
-rw-r--r--compiler/hsSyn/HsTypes.lhs21
-rw-r--r--compiler/iface/BinIface.hs22
-rw-r--r--compiler/iface/IfaceEnv.lhs24
-rw-r--r--compiler/iface/IfaceType.lhs19
-rw-r--r--compiler/iface/TcIface.lhs2
-rw-r--r--compiler/main/DynFlags.hs5
-rw-r--r--compiler/main/HscTypes.lhs10
-rw-r--r--compiler/parser/Parser.y.pp6
-rw-r--r--compiler/prelude/PrelNames.lhs15
-rw-r--r--compiler/prelude/TysWiredIn.lhs41
-rw-r--r--compiler/rename/RnBinds.lhs7
-rw-r--r--compiler/rename/RnExpr.lhs3
-rw-r--r--compiler/rename/RnTypes.lhs11
-rw-r--r--compiler/typecheck/Inst.lhs2
-rw-r--r--compiler/typecheck/TcBinds.lhs27
-rw-r--r--compiler/typecheck/TcCanonical.lhs46
-rw-r--r--compiler/typecheck/TcErrors.lhs6
-rw-r--r--compiler/typecheck/TcExpr.lhs27
-rw-r--r--compiler/typecheck/TcHsSyn.lhs11
-rw-r--r--compiler/typecheck/TcHsType.lhs6
-rw-r--r--compiler/typecheck/TcInteract.lhs114
-rw-r--r--compiler/typecheck/TcMType.lhs42
-rw-r--r--compiler/typecheck/TcRnTypes.lhs23
-rw-r--r--compiler/typecheck/TcSMonad.lhs25
-rw-r--r--compiler/typecheck/TcSimplify.lhs65
-rw-r--r--compiler/typecheck/TcSplice.lhs8
-rw-r--r--compiler/typecheck/TcType.lhs5
-rw-r--r--compiler/types/IParam.lhs41
-rw-r--r--compiler/types/IParam.lhs-boot10
-rw-r--r--compiler/types/TyCon.lhs15
-rw-r--r--compiler/types/Type.lhs42
-rw-r--r--compiler/types/TypeRep.lhs12
39 files changed, 309 insertions, 480 deletions
diff --git a/compiler/basicTypes/BasicTypes.lhs b/compiler/basicTypes/BasicTypes.lhs
index 6db5788d2f..86b93ab9a2 100644
--- a/compiler/basicTypes/BasicTypes.lhs
+++ b/compiler/basicTypes/BasicTypes.lhs
@@ -39,8 +39,6 @@ module BasicTypes(
negateFixity, funTyFixity,
compareFixity,
- IPName(..), ipNameName, mapIPName,
-
RecFlag(..), isRec, isNonRec, boolToRecFlag,
RuleName,
@@ -178,32 +176,6 @@ instance Outputable WarningTxt where
%************************************************************************
%* *
-\subsection{Implicit parameter identity}
-%* *
-%************************************************************************
-
-The @IPName@ type is here because it is used in TypeRep (i.e. very
-early in the hierarchy), but also in HsSyn.
-
-\begin{code}
-newtype IPName name = IPName name -- ?x
- deriving( Eq, Data, Typeable )
-
-instance Functor IPName where
- fmap = mapIPName
-
-ipNameName :: IPName name -> name
-ipNameName (IPName n) = n
-
-mapIPName :: (a->b) -> IPName a -> IPName b
-mapIPName f (IPName n) = IPName (f n)
-
-instance Outputable name => Outputable (IPName name) where
- ppr (IPName n) = char '?' <> ppr n -- Ordinary implicit parameters
-\end{code}
-
-%************************************************************************
-%* *
Rules
%* *
%************************************************************************
diff --git a/compiler/basicTypes/Unique.lhs b/compiler/basicTypes/Unique.lhs
index 39b30d93f7..48afc8da41 100644
--- a/compiler/basicTypes/Unique.lhs
+++ b/compiler/basicTypes/Unique.lhs
@@ -179,9 +179,6 @@ instance Uniquable FastString where
instance Uniquable Int where
getUnique i = mkUniqueGrimily i
-
-instance Uniquable n => Uniquable (IPName n) where
- getUnique (IPName n) = getUnique n
\end{code}
diff --git a/compiler/coreSyn/MkCore.lhs b/compiler/coreSyn/MkCore.lhs
index 25dfaababa..6123e0a346 100644
--- a/compiler/coreSyn/MkCore.lhs
+++ b/compiler/coreSyn/MkCore.lhs
@@ -25,9 +25,6 @@ module MkCore (
-- * Floats
FloatBind(..), wrapFloat,
- -- * Constructing/deconstructing implicit parameter boxes
- mkIPUnbox, mkIPBox,
-
-- * Constructing/deconstructing equality evidence boxes
mkEqBox,
@@ -62,7 +59,7 @@ module MkCore (
#include "HsVersions.h"
import Id
-import Var ( IpId, EvVar, setTyVarUnique )
+import Var ( EvVar, setTyVarUnique )
import CoreSyn
import CoreUtils ( exprType, needsCaseBinding, bindNonRec )
@@ -72,8 +69,7 @@ import HscTypes
import TysWiredIn
import PrelNames
-import IParam ( ipCoAxiom )
-import TcType ( mkSigmaTy, evVarPred )
+import TcType ( mkSigmaTy )
import Type
import Coercion
import TysPrim
@@ -303,21 +299,6 @@ mkStringExprFS str
\begin{code}
-mkIPBox :: IPName IpId -> CoreExpr -> CoreExpr
-mkIPBox ipx e = e `Cast` mkSymCo (mkAxInstCo (ipCoAxiom ip) [ty])
- where x = ipNameName ipx
- Just (ip, ty) = getIPPredTy_maybe (evVarPred x)
- -- NB: don't use the DataCon work id because we don't generate code for it
-
-mkIPUnbox :: IPName IpId -> CoreExpr
-mkIPUnbox ipx = Var x `Cast` mkAxInstCo (ipCoAxiom ip) [ty]
- where x = ipNameName ipx
- Just (ip, ty) = getIPPredTy_maybe (evVarPred x)
-
-\end{code}
-
-\begin{code}
-
mkEqBox :: Coercion -> CoreExpr
mkEqBox co = ASSERT2( typeKind ty2 `eqKind` k, ppr co $$ ppr ty1 $$ ppr ty2 $$ ppr (typeKind ty1) $$ ppr (typeKind ty2) )
Var (dataConWorkId eqBoxDataCon) `mkTyApps` [k, ty1, ty2] `App` Coercion co
diff --git a/compiler/deSugar/DsExpr.lhs b/compiler/deSugar/DsExpr.lhs
index a60d3c4a80..11fa5d53c9 100644
--- a/compiler/deSugar/DsExpr.lhs
+++ b/compiler/deSugar/DsExpr.lhs
@@ -86,9 +86,9 @@ dsIPBinds (IPBinds ip_binds ev_binds) body
-- dependency order; hence Rec
; foldrM ds_ip_bind inner ip_binds }
where
- ds_ip_bind (L _ (IPBind n e)) body
+ ds_ip_bind (L _ (IPBind ~(Right n) e)) body
= do e' <- dsLExpr e
- return (Let (NonRec (ipNameName n) (mkIPBox n e')) body)
+ return (Let (NonRec n e') body)
-------------------------
ds_val_bind :: (RecFlag, LHsBinds Id) -> CoreExpr -> DsM CoreExpr
@@ -188,7 +188,7 @@ dsExpr :: HsExpr Id -> DsM CoreExpr
dsExpr (HsPar e) = dsLExpr e
dsExpr (ExprWithTySigOut e _) = dsLExpr e
dsExpr (HsVar var) = return (varToCoreExpr var) -- See Note [Desugaring vars]
-dsExpr (HsIPVar ip) = return (mkIPUnbox ip)
+dsExpr (HsIPVar _) = panic "dsExpr: HsIPVar"
dsExpr (HsLit lit) = dsLit lit
dsExpr (HsOverLit lit) = dsOverLit lit
diff --git a/compiler/ghc.cabal.in b/compiler/ghc.cabal.in
index bfd44384bb..4371bca95e 100644
--- a/compiler/ghc.cabal.in
+++ b/compiler/ghc.cabal.in
@@ -404,7 +404,6 @@ Library
TcCanonical
TcSMonad
Class
- IParam
Coercion
FamInstEnv
FunDeps
diff --git a/compiler/hsSyn/HsBinds.lhs b/compiler/hsSyn/HsBinds.lhs
index 3fd7efc538..7de9018dbe 100644
--- a/compiler/hsSyn/HsBinds.lhs
+++ b/compiler/hsSyn/HsBinds.lhs
@@ -416,10 +416,12 @@ isEmptyIPBinds (IPBinds is ds) = null is && isEmptyTcEvBinds ds
type LIPBind id = Located (IPBind id)
-- | Implicit parameter bindings.
+{- These bindings start off as (Left "x") in the parser and stay
+that way until after type-checking when they are replaced with
+(Right d), where "d" is the name of the dictionary holding the
+evidene for the implicit parameter. -}
data IPBind id
- = IPBind
- (IPName id)
- (LHsExpr id)
+ = IPBind (Either HsIPName id) (LHsExpr id)
deriving (Data, Typeable)
instance (OutputableBndr id) => Outputable (HsIPBinds id) where
@@ -427,7 +429,10 @@ instance (OutputableBndr id) => Outputable (HsIPBinds id) where
$$ ifPprDebug (ppr ds)
instance (OutputableBndr id) => Outputable (IPBind id) where
- ppr (IPBind id rhs) = pprBndr LetBind id <+> equals <+> pprExpr (unLoc rhs)
+ ppr (IPBind lr rhs) = name <+> equals <+> pprExpr (unLoc rhs)
+ where name = case lr of
+ Left ip -> pprBndr LetBind ip
+ Right id -> pprBndr LetBind id
\end{code}
diff --git a/compiler/hsSyn/HsExpr.lhs b/compiler/hsSyn/HsExpr.lhs
index c7f4459d6e..dcfcb9f8f0 100644
--- a/compiler/hsSyn/HsExpr.lhs
+++ b/compiler/hsSyn/HsExpr.lhs
@@ -106,7 +106,7 @@ noSyntaxTable = []
-- | A Haskell expression.
data HsExpr id
= HsVar id -- ^ variable
- | HsIPVar (IPName id) -- ^ implicit parameter
+ | HsIPVar HsIPName -- ^ implicit parameter
| HsOverLit (HsOverLit id) -- ^ Overloaded literals
| HsLit HsLit -- ^ Simple (non-overloaded) literals
diff --git a/compiler/hsSyn/HsTypes.lhs b/compiler/hsSyn/HsTypes.lhs
index eec87c4ded..a57c48a1c6 100644
--- a/compiler/hsSyn/HsTypes.lhs
+++ b/compiler/hsSyn/HsTypes.lhs
@@ -18,6 +18,7 @@ module HsTypes (
HsQuasiQuote(..),
HsTyWrapper(..),
HsTyLit(..),
+ HsIPName(..), hsIPNameFS,
LBangType, BangType, HsBang(..),
getBangType, getBangStrictness,
@@ -158,6 +159,24 @@ mkHsWithBndrs :: thing -> HsWithBndrs thing
mkHsWithBndrs x = HsWB { hswb_cts = x, hswb_kvs = panic "mkHsTyWithBndrs:kvs"
, hswb_tvs = panic "mkHsTyWithBndrs:tvs" }
+
+-- | These names are used eary on to store the names of implicit
+-- parameters. They completely disappear after type-checking.
+newtype HsIPName = HsIPName FastString-- ?x
+ deriving( Eq, Data, Typeable )
+
+hsIPNameFS :: HsIPName -> FastString
+hsIPNameFS (HsIPName n) = n
+
+instance Outputable HsIPName where
+ ppr (HsIPName n) = char '?' <> ftext n -- Ordinary implicit parameters
+
+instance OutputableBndr HsIPName where
+ pprBndr _ n = ppr n -- Simple for now
+ pprInfixOcc n = ppr n
+ pprPrefixOcc n = ppr n
+
+
data HsTyVarBndr name
= UserTyVar -- No explicit kinding
name -- See Note [Printing KindedTyVars]
@@ -201,7 +220,7 @@ data HsType name
-- Parenthesis preserved for the precedence re-arrangement in RnTypes
-- It's important that a * (b + c) doesn't get rearranged to (a*b) + c!
- | HsIParamTy (IPName name) -- (?x :: ty)
+ | HsIParamTy HsIPName -- (?x :: ty)
(LHsType name) -- Implicit parameters as they occur in contexts
| HsEqTy (LHsType name) -- ty1 ~ ty2
diff --git a/compiler/iface/BinIface.hs b/compiler/iface/BinIface.hs
index 5d1c48f183..f03808fbd2 100644
--- a/compiler/iface/BinIface.hs
+++ b/compiler/iface/BinIface.hs
@@ -19,9 +19,8 @@ module BinIface (
#include "HsVersions.h"
import TcRnMonad
-import TyCon (TyCon, tyConName, tupleTyConSort, tupleTyConArity, isTupleTyCon, tyConIP_maybe)
+import TyCon (TyCon, tyConName, tupleTyConSort, tupleTyConArity, isTupleTyCon)
import DataCon (dataConName, dataConWorkId, dataConTyCon)
-import IParam (ipFastString, ipTyConName)
import PrelInfo (wiredInThings, basicKnownKeyNames)
import Id (idName, isDataConWorkId_maybe)
import TysWiredIn
@@ -316,7 +315,7 @@ knownKeyNamesMap = listToUFM_Directly [(nameUnique n, n) | n <- knownKeyNames]
-- See Note [Symbol table representation of names]
putName :: BinDictionary -> BinSymbolTable -> BinHandle -> Name -> IO ()
-putName dict BinSymbolTable{
+putName _dict BinSymbolTable{
bin_symtab_map = symtab_map_ref,
bin_symtab_next = symtab_next } bh name
| name `elemUFM` knownKeyNamesMap
@@ -327,10 +326,6 @@ putName dict BinSymbolTable{
= case wiredInNameTyThing_maybe name of
Just (ATyCon tc)
| isTupleTyCon tc -> putTupleName_ bh tc 0
- | Just ip <- tyConIP_maybe tc -> do
- off <- allocateFastString dict (ipFastString ip)
- -- MASSERT(off < 2^(30 :: Int))
- put_ bh (0xC0000000 .|. off)
Just (ADataCon dc)
| let tc = dataConTyCon dc, isTupleTyCon tc -> putTupleName_ bh tc 1
Just (AnId x)
@@ -362,7 +357,7 @@ putTupleName_ bh tc thing_tag
getSymtabName :: NameCacheUpdater
-> Dictionary -> SymbolTable
-> BinHandle -> IO Name
-getSymtabName ncu dict symtab bh = do
+getSymtabName _ncu _dict symtab bh = do
i <- get bh
case i .&. 0xC0000000 of
0x00000000 -> return $! symtab ! fromIntegral (i ::  Word32)
@@ -385,7 +380,6 @@ getSymtabName ncu dict symtab bh = do
_ -> pprPanic "getSymtabName:unknown tuple sort" (ppr i)
thing_tag = (i .&. 0x0CFFFFFF) `shiftR` 26
arity = fromIntegral (i .&. 0x03FFFFFF)
- 0xC0000000 -> liftM ipTyConName $ updateNameCache ncu $ flip allocateIPName (dict ! fromIntegral (i .&. 0x3FFFFFFF))
_ -> pprPanic "getSymtabName:unknown name tag" (ppr i)
data BinSymbolTable = BinSymbolTable {
@@ -426,7 +420,6 @@ data BinDictionary = BinDictionary {
-- All the binary instances
-- BasicTypes
-{-! for IPName derive: Binary !-}
{-! for Fixity derive: Binary !-}
{-! for FixityDirection derive: Binary !-}
{-! for Boxity derive: Binary !-}
@@ -825,11 +818,6 @@ instance Binary Fixity where
ab <- get bh
return (Fixity aa ab)
-instance (Binary name) => Binary (IPName name) where
- put_ bh (IPName aa) = put_ bh aa
- get bh = do aa <- get bh
- return (IPName aa)
-
-------------------------------------------------------------------------
-- Types from: Demand
-------------------------------------------------------------------------
@@ -1057,8 +1045,7 @@ instance Binary IfaceCoCon where
put_ bh IfaceTransCo = putByte bh 4
put_ bh IfaceInstCo = putByte bh 5
put_ bh (IfaceNthCo d) = do { putByte bh 6; put_ bh d }
- put_ bh (IfaceIPCoAx ip) = do { putByte bh 7; put_ bh ip }
-
+
get bh = do
h <- getByte bh
case h of
@@ -1069,7 +1056,6 @@ instance Binary IfaceCoCon where
4 -> return IfaceTransCo
5 -> return IfaceInstCo
6 -> do { d <- get bh; return (IfaceNthCo d) }
- 7 -> do { ip <- get bh; return (IfaceIPCoAx ip) }
_ -> panic ("get IfaceCoCon " ++ show h)
-------------------------------------------------------------------------
diff --git a/compiler/iface/IfaceEnv.lhs b/compiler/iface/IfaceEnv.lhs
index 1e776f52a3..20a21c3733 100644
--- a/compiler/iface/IfaceEnv.lhs
+++ b/compiler/iface/IfaceEnv.lhs
@@ -12,14 +12,14 @@ module IfaceEnv (
newGlobalBinder, newImplicitBinder,
lookupIfaceTop,
lookupOrig, lookupOrigNameCache, extendNameCache,
- newIPName, newIfaceName, newIfaceNames,
+ newIfaceName, newIfaceNames,
extendIfaceIdEnv, extendIfaceTyVarEnv,
tcIfaceLclId, tcIfaceTyVar, lookupIfaceTyVar,
ifaceExportNames,
-- Name-cache stuff
- allocateGlobalBinder, allocateIPName, initNameCache, updNameCache,
+ allocateGlobalBinder, initNameCache, updNameCache,
getNameCache, mkNameCacheUpdater, NameCacheUpdater(..)
) where
@@ -40,14 +40,12 @@ import UniqFM
import FastString
import UniqSupply
import SrcLoc
-import BasicTypes
import Util
import Outputable
import Exception ( evaluate )
import Data.IORef ( atomicModifyIORef, readIORef )
-import qualified Data.Map as Map
\end{code}
@@ -165,21 +163,6 @@ lookupOrig mod occ
new_cache = extendNameCache (nsNames name_cache) mod occ name
in (name_cache{ nsUniqs = us, nsNames = new_cache }, name)
}}}
-
-allocateIPName :: NameCache -> FastString -> (NameCache, IPName Name)
-allocateIPName name_cache ip = case Map.lookup ip ipcache of
- Just name_ip -> (name_cache, name_ip)
- Nothing -> (new_ns, name_ip)
- where
- (us_here, us') = splitUniqSupply (nsUniqs name_cache)
- tycon_u:datacon_u:dc_wrk_u:co_ax_u:_ = uniqsFromSupply us_here
- name_ip = mkIPName ip tycon_u datacon_u dc_wrk_u co_ax_u
- new_ipcache = Map.insert ip name_ip ipcache
- new_ns = name_cache {nsUniqs = us', nsIPs = new_ipcache}
- where ipcache = nsIPs name_cache
-
-newIPName :: FastString -> TcRnIf m n (IPName Name)
-newIPName ip = updNameCache $ flip allocateIPName ip
\end{code}
%************************************************************************
@@ -249,8 +232,7 @@ mkNameCacheUpdater = do
initNameCache :: UniqSupply -> [Name] -> NameCache
initNameCache us names
= NameCache { nsUniqs = us,
- nsNames = initOrigNames names,
- nsIPs = Map.empty }
+ nsNames = initOrigNames names }
initOrigNames :: [Name] -> OrigNameCache
initOrigNames names = foldl extendOrigNameCache emptyModuleEnv names
diff --git a/compiler/iface/IfaceType.lhs b/compiler/iface/IfaceType.lhs
index 6b7a33771f..c484b0637f 100644
--- a/compiler/iface/IfaceType.lhs
+++ b/compiler/iface/IfaceType.lhs
@@ -14,7 +14,7 @@ This module defines interface types and binders
-- for details
module IfaceType (
- IfExtName, IfLclName, IfIPName,
+ IfExtName, IfLclName,
IfaceType(..), IfacePredType, IfaceKind, IfaceTyCon(..), IfaceCoCon(..),
IfaceTyLit(..),
@@ -37,8 +37,6 @@ module IfaceType (
import Coercion
import TypeRep hiding( maybeParen )
-import Type (tyConAppTyCon_maybe)
-import IParam (ipFastString)
import TyCon
import Id
import Var
@@ -62,8 +60,6 @@ type IfLclName = FastString -- A local name in iface syntax
type IfExtName = Name -- An External or WiredIn Name can appear in IfaceSyn
-- (However Internal or System Names never should)
-type IfIPName = FastString -- Represent implicit parameters simply as a string
-
data IfaceBndr -- Local (non-top-level) binders
= IfaceIdBndr {-# UNPACK #-} !IfaceIdBndr
| IfaceTvBndr {-# UNPACK #-} !IfaceTvBndr
@@ -99,7 +95,6 @@ newtype IfaceTyCon = IfaceTc { ifaceTyConName :: IfExtName }
-- Coercion constructors
data IfaceCoCon
= IfaceCoAx IfExtName
- | IfaceIPCoAx FastString
| IfaceReflCo | IfaceUnsafeCo | IfaceSymCo
| IfaceTransCo | IfaceInstCo
| IfaceNthCo Int
@@ -253,10 +248,6 @@ ppr_tc_app _ (IfaceTc n) tys
, Just sort <- tyConTuple_maybe tc
, tyConArity tc == length tys
= tupleParens sort (sep (punctuate comma (map pprIfaceType tys)))
- | Just (ATyCon tc) <- wiredInNameTyThing_maybe n
- , Just ip <- tyConIP_maybe tc
- , [ty] <- tys
- = parens (ppr ip <> dcolon <> pprIfaceType ty)
ppr_tc_app ctxt_prec tc tys
= maybeParen ctxt_prec tYCON_PREC
(sep [ppr_tc tc, nest 4 (sep (map pprParendIfaceType tys))])
@@ -279,7 +270,6 @@ instance Outputable IfaceTyCon where
instance Outputable IfaceCoCon where
ppr (IfaceCoAx n) = ppr n
- ppr (IfaceIPCoAx ip) = ppr (IPName ip)
ppr IfaceReflCo = ptext (sLit "Refl")
ppr IfaceUnsafeCo = ptext (sLit "Unsafe")
ppr IfaceSymCo = ptext (sLit "Sym")
@@ -386,11 +376,6 @@ coToIfaceType (InstCo co ty) = IfaceCoConApp IfaceInstCo
, toIfaceType ty ]
coAxiomToIfaceType :: CoAxiom -> IfaceCoCon
-coAxiomToIfaceType con
- | Just tc <- tyConAppTyCon_maybe (co_ax_lhs con)
- , Just ip <- tyConIP_maybe tc
- = IfaceIPCoAx (ipFastString ip)
- | otherwise
- = IfaceCoAx (coAxiomName con)
+coAxiomToIfaceType con = IfaceCoAx (coAxiomName con)
\end{code}
diff --git a/compiler/iface/TcIface.lhs b/compiler/iface/TcIface.lhs
index 18c9a8cba9..e63bf7268f 100644
--- a/compiler/iface/TcIface.lhs
+++ b/compiler/iface/TcIface.lhs
@@ -37,7 +37,6 @@ import Id
import MkId
import IdInfo
import Class
-import IParam
import TyCon
import DataCon
import PrelNames
@@ -958,7 +957,6 @@ tcIfaceCo (IfaceForAllTy tv t) = bindIfaceTyVar tv $ \ tv' ->
tcIfaceCoApp :: IfaceCoCon -> [IfaceType] -> IfL Coercion
tcIfaceCoApp IfaceReflCo [t] = Refl <$> tcIfaceType t
tcIfaceCoApp (IfaceCoAx n) ts = AxiomInstCo <$> tcIfaceCoAxiom n <*> mapM tcIfaceCo ts
-tcIfaceCoApp (IfaceIPCoAx ip) ts = AxiomInstCo <$> liftM ipCoAxiom (newIPName ip) <*> mapM tcIfaceCo ts
tcIfaceCoApp IfaceUnsafeCo [t1,t2] = UnsafeCo <$> tcIfaceType t1 <*> tcIfaceType t2
tcIfaceCoApp IfaceSymCo [t] = SymCo <$> tcIfaceCo t
tcIfaceCoApp IfaceTransCo [t1,t2] = TransCo <$> tcIfaceCo t1 <*> tcIfaceCo t2
diff --git a/compiler/main/DynFlags.hs b/compiler/main/DynFlags.hs
index 484744373d..f5fc45aab3 100644
--- a/compiler/main/DynFlags.hs
+++ b/compiler/main/DynFlags.hs
@@ -2174,6 +2174,11 @@ impliedFlags
, (Opt_RecordWildCards, turnOn, Opt_DisambiguateRecordFields)
, (Opt_ParallelArrays, turnOn, Opt_ParallelListComp)
+
+ -- An implicit parameter constraint, `?x::Int`, is desugared into
+ -- `IP "x" Int`, which requires a flexible context/instance.
+ , (Opt_ImplicitParams, turnOn, Opt_FlexibleContexts)
+ , (Opt_ImplicitParams, turnOn, Opt_FlexibleInstances)
]
optLevelFlags :: [([Int], DynFlag)]
diff --git a/compiler/main/HscTypes.lhs b/compiler/main/HscTypes.lhs
index 6d1a9c02fb..1631e8ccaf 100644
--- a/compiler/main/HscTypes.lhs
+++ b/compiler/main/HscTypes.lhs
@@ -73,7 +73,7 @@ module HscTypes (
-- * Information on imports and exports
WhetherHasOrphans, IsBootInterface, Usage(..),
Dependencies(..), noDependencies,
- NameCache(..), OrigNameCache, OrigIParamCache,
+ NameCache(..), OrigNameCache,
IfaceExport,
-- * Warnings
@@ -162,7 +162,6 @@ import Util
import Control.Monad ( mplus, guard, liftM, when )
import Data.Array ( Array, array )
import Data.IORef
-import Data.Map ( Map )
import Data.Time
import Data.Word
import Data.Typeable ( Typeable )
@@ -1763,17 +1762,12 @@ its binding site, we fix it up.
data NameCache
= NameCache { nsUniqs :: UniqSupply,
-- ^ Supply of uniques
- nsNames :: OrigNameCache,
+ nsNames :: OrigNameCache
-- ^ Ensures that one original name gets one unique
- nsIPs :: OrigIParamCache
- -- ^ Ensures that one implicit parameter name gets one unique
}
-- | Per-module cache of original 'OccName's given 'Name's
type OrigNameCache = ModuleEnv (OccEnv Name)
-
--- | Module-local cache of implicit parameter 'OccName's given 'Name's
-type OrigIParamCache = Map FastString (IPName Name)
\end{code}
diff --git a/compiler/parser/Parser.y.pp b/compiler/parser/Parser.y.pp
index 759d5449f9..21f8782f6f 100644
--- a/compiler/parser/Parser.y.pp
+++ b/compiler/parser/Parser.y.pp
@@ -1762,10 +1762,10 @@ dbinds :: { Located [LIPBind RdrName] }
-- | {- empty -} { [] }
dbind :: { LIPBind RdrName }
-dbind : ipvar '=' exp { LL (IPBind (unLoc $1) $3) }
+dbind : ipvar '=' exp { LL (IPBind (Left (unLoc $1)) $3) }
-ipvar :: { Located (IPName RdrName) }
- : IPDUPVARID { L1 (IPName (mkUnqual varName (getIPDUPVARID $1))) }
+ipvar :: { Located HsIPName }
+ : IPDUPVARID { L1 (HsIPName (getIPDUPVARID $1)) }
-----------------------------------------------------------------------------
-- Warnings and deprecations
diff --git a/compiler/prelude/PrelNames.lhs b/compiler/prelude/PrelNames.lhs
index 5af98df4e8..3a39d531bb 100644
--- a/compiler/prelude/PrelNames.lhs
+++ b/compiler/prelude/PrelNames.lhs
@@ -285,6 +285,9 @@ basicKnownKeyNames
typeNatMulTyFamName,
typeNatExpTyFamName,
+ -- Implicit parameters
+ ipClassName,
+
-- Annotation type checking
toAnnotationWrapperName
@@ -348,7 +351,7 @@ gHC_PRIM, gHC_TYPES, gHC_GENERICS,
gHC_FLOAT, gHC_TOP_HANDLER, sYSTEM_IO, dYNAMIC, tYPEABLE, tYPEABLE_INTERNAL, gENERICS,
dOTNET, rEAD_PREC, lEX, gHC_INT, gHC_WORD, mONAD, mONAD_FIX, mONAD_ZIP,
aRROW, cONTROL_APPLICATIVE, gHC_DESUGAR, rANDOM, gHC_EXTS,
- cONTROL_EXCEPTION_BASE, gHC_TYPELITS :: Module
+ cONTROL_EXCEPTION_BASE, gHC_TYPELITS, gHC_IP :: Module
gHC_PRIM = mkPrimModule (fsLit "GHC.Prim") -- Primitive types and values
gHC_TYPES = mkPrimModule (fsLit "GHC.Types")
@@ -402,6 +405,7 @@ rANDOM = mkBaseModule (fsLit "System.Random")
gHC_EXTS = mkBaseModule (fsLit "GHC.Exts")
cONTROL_EXCEPTION_BASE = mkBaseModule (fsLit "Control.Exception.Base")
gHC_TYPELITS = mkBaseModule (fsLit "GHC.TypeLits")
+gHC_IP = mkBaseModule (fsLit "GHC.IP")
gHC_PARR' :: Module
gHC_PARR' = mkBaseModule (fsLit "GHC.PArr")
@@ -1081,6 +1085,12 @@ typeNatAddTyFamName = tcQual gHC_TYPELITS (fsLit "+") typeNatAddTyFamNameKey
typeNatMulTyFamName = tcQual gHC_TYPELITS (fsLit "*") typeNatMulTyFamNameKey
typeNatExpTyFamName = tcQual gHC_TYPELITS (fsLit "^") typeNatExpTyFamNameKey
+-- Implicit parameters
+ipClassName :: Name
+ipClassName = clsQual gHC_IP (fsLit "IP") ipClassNameKey
+
+
+
-- dotnet interop
objectTyConName :: Name
objectTyConName = tcQual dOTNET (fsLit "Object") objectTyConKey
@@ -1201,6 +1211,9 @@ typeNatLeqClassNameKey = mkPreludeClassUnique 43
ghciIoClassKey :: Unique
ghciIoClassKey = mkPreludeClassUnique 44
+
+ipClassNameKey :: Unique
+ipClassNameKey = mkPreludeClassUnique 45
\end{code}
%************************************************************************
diff --git a/compiler/prelude/TysWiredIn.lhs b/compiler/prelude/TysWiredIn.lhs
index 60518bfd9f..78e1f74b4d 100644
--- a/compiler/prelude/TysWiredIn.lhs
+++ b/compiler/prelude/TysWiredIn.lhs
@@ -72,8 +72,6 @@ module TysWiredIn (
-- * Equality predicates
eqTyCon_RDR, eqTyCon, eqTyConName, eqBoxDataCon,
- -- * Implicit parameter predicates
- mkIPName
) where
#include "HsVersions.h"
@@ -85,7 +83,6 @@ import PrelNames
import TysPrim
-- others:
-import Coercion
import Constants ( mAX_TUPLE_SIZE )
import Module ( Module )
import Type ( mkTyConApp )
@@ -95,7 +92,7 @@ import TyCon
import TypeRep
import RdrName
import Name
-import BasicTypes ( TupleSort(..), tupleSortBoxity, IPName(..),
+import BasicTypes ( TupleSort(..), tupleSortBoxity,
Arity, RecFlag(..), Boxity(..), HsBang(..) )
import ForeignCall
import Unique ( incrUnique, mkTupleTyConUnique,
@@ -254,9 +251,6 @@ pcTyCon is_enum is_rec name cType tyvars cons
pcDataCon :: Name -> [TyVar] -> [Type] -> TyCon -> DataCon
pcDataCon = pcDataConWithFixity False
-pcDataCon' :: Name -> Unique -> [TyVar] -> [Type] -> TyCon -> DataCon
-pcDataCon' = pcDataConWithFixity' False
-
pcDataConWithFixity :: Bool -> Name -> [TyVar] -> [Type] -> TyCon -> DataCon
pcDataConWithFixity infx n = pcDataConWithFixity' infx n (incrUnique (nameUnique n))
-- The Name's unique is the first of two free uniques;
@@ -395,39 +389,6 @@ unboxedPairDataCon :: DataCon
unboxedPairDataCon = tupleCon UnboxedTuple 2
\end{code}
-%************************************************************************
-%* *
-\subsection[TysWiredIn-ImplicitParams]{Special type constructors for implicit parameters}
-%* *
-%************************************************************************
-
-\begin{code}
-mkIPName :: FastString
- -> Unique -> Unique -> Unique -> Unique
- -> IPName Name
-mkIPName ip tycon_u datacon_u dc_wrk_u co_ax_u = name_ip
- where
- name_ip = IPName tycon_name
-
- tycon_name = mkPrimTyConName ip tycon_u tycon
- tycon = mkAlgTyCon tycon_name
- (liftedTypeKind `mkArrowKind` constraintKind)
- [alphaTyVar]
- Nothing
- [] -- No stupid theta
- (NewTyCon { data_con = datacon,
- nt_rhs = mkTyVarTy alphaTyVar,
- nt_etad_rhs = ([alphaTyVar], mkTyVarTy alphaTyVar),
- nt_co = mkNewTypeCo co_ax_name tycon [alphaTyVar] (mkTyVarTy alphaTyVar) })
- (IPTyCon name_ip)
- NonRecursive
- False
-
- datacon_name = mkWiredInDataConName UserSyntax gHC_TYPES (fsLit "IPBox") datacon_u datacon
- datacon = pcDataCon' datacon_name dc_wrk_u [alphaTyVar] [mkTyVarTy alphaTyVar] tycon
-
- co_ax_name = mkPrimTyConName ip co_ax_u tycon
-\end{code}
%************************************************************************
%* *
diff --git a/compiler/rename/RnBinds.lhs b/compiler/rename/RnBinds.lhs
index 536d83b344..d3d16033eb 100644
--- a/compiler/rename/RnBinds.lhs
+++ b/compiler/rename/RnBinds.lhs
@@ -35,7 +35,7 @@ import {-# SOURCE #-} RnExpr( rnLExpr, rnStmts )
import HsSyn
import TcRnMonad
import TcEvidence ( emptyTcEvBinds )
-import RnTypes ( bindSigTyVarsFV, rnIPName, rnHsSigType, rnLHsType, checkPrecMatch )
+import RnTypes ( bindSigTyVarsFV, rnHsSigType, rnLHsType, checkPrecMatch )
import RnPat
import RnEnv
import DynFlags
@@ -220,10 +220,9 @@ rnIPBinds (IPBinds ip_binds _no_dict_binds) = do
return (IPBinds ip_binds' emptyTcEvBinds, plusFVs fvs_s)
rnIPBind :: IPBind RdrName -> RnM (IPBind Name, FreeVars)
-rnIPBind (IPBind n expr) = do
- n' <- rnIPName n
+rnIPBind (IPBind ~(Left n) expr) = do
(expr',fvExpr) <- rnLExpr expr
- return (IPBind n' expr', fvExpr)
+ return (IPBind (Left n) expr', fvExpr)
\end{code}
diff --git a/compiler/rename/RnExpr.lhs b/compiler/rename/RnExpr.lhs
index 3bb56ebfda..d27ef98e80 100644
--- a/compiler/rename/RnExpr.lhs
+++ b/compiler/rename/RnExpr.lhs
@@ -111,8 +111,7 @@ rnExpr (HsVar v)
finishHsVar name
rnExpr (HsIPVar v)
- = do v' <- rnIPName v
- return (HsIPVar v', emptyFVs)
+ = return (HsIPVar v, emptyFVs)
rnExpr (HsLit lit@(HsString s))
= do {
diff --git a/compiler/rename/RnTypes.lhs b/compiler/rename/RnTypes.lhs
index ecdfdaf36e..ed2144084a 100644
--- a/compiler/rename/RnTypes.lhs
+++ b/compiler/rename/RnTypes.lhs
@@ -16,7 +16,7 @@ module RnTypes (
rnHsType, rnLHsType, rnLHsTypes, rnContext,
rnHsKind, rnLHsKind, rnLHsMaybeKind,
rnHsSigType, rnLHsInstType, rnConDeclFields,
- rnIPName, newTyVarNameRn,
+ newTyVarNameRn,
-- Precence related stuff
mkOpAppRn, mkNegAppRn, mkOpFormRn, mkConOpPatRn,
@@ -41,7 +41,6 @@ import HsSyn
import RnHsDoc ( rnLHsDoc, rnMbLHsDoc )
import RnEnv
import TcRnMonad
-import IfaceEnv ( newIPName )
import RdrName
import PrelNames
import TysPrim ( funTyConName )
@@ -50,7 +49,7 @@ import SrcLoc
import NameSet
import Util
-import BasicTypes ( IPName(..), ipNameName, compareFixity, funTyFixity, negateFixity,
+import BasicTypes ( compareFixity, funTyFixity, negateFixity,
Fixity(..), FixityDirection(..) )
import Outputable
import FastString
@@ -248,8 +247,7 @@ rnHsTyKi isType doc (HsAppTy ty1 ty2)
rnHsTyKi isType doc (HsIParamTy n ty)
= ASSERT( isType )
do { (ty', fvs) <- rnLHsType doc ty
- ; n' <- rnIPName n
- ; return (HsIParamTy n' ty', fvs) }
+ ; return (HsIParamTy n ty', fvs) }
rnHsTyKi isType doc (HsEqTy ty1 ty2)
= ASSERT( isType )
@@ -494,9 +492,6 @@ rnContext :: HsDocContext -> LHsContext RdrName -> RnM (LHsContext Name, FreeVar
rnContext doc (L loc cxt)
= do { (cxt', fvs) <- rnLHsTypes doc cxt
; return (L loc cxt', fvs) }
-
-rnIPName :: IPName RdrName -> RnM (IPName Name)
-rnIPName n = newIPName (occNameFS (rdrNameOcc (ipNameName n)))
\end{code}
diff --git a/compiler/typecheck/Inst.lhs b/compiler/typecheck/Inst.lhs
index 993bcebdb5..bbad59ec6e 100644
--- a/compiler/typecheck/Inst.lhs
+++ b/compiler/typecheck/Inst.lhs
@@ -519,7 +519,6 @@ hasEqualities givens = any (has_eq . evVarPred) givens
-- See Note [Float Equalities out of Implications] in TcSimplify
has_eq' (EqPred {}) = True
- has_eq' (IPPred {}) = False
has_eq' (ClassPred cls _tys) = any has_eq (classSCTheta cls)
has_eq' (TuplePred ts) = any has_eq ts
has_eq' (IrredPred _) = True -- Might have equalities in it after reduction?
@@ -529,7 +528,6 @@ tyVarsOfCt :: Ct -> TcTyVarSet
tyVarsOfCt (CTyEqCan { cc_tyvar = tv, cc_rhs = xi }) = extendVarSet (tyVarsOfType xi) tv
tyVarsOfCt (CFunEqCan { cc_tyargs = tys, cc_rhs = xi }) = tyVarsOfTypes (xi:tys)
tyVarsOfCt (CDictCan { cc_tyargs = tys }) = tyVarsOfTypes tys
-tyVarsOfCt (CIPCan { cc_ip_ty = ty }) = tyVarsOfType ty
tyVarsOfCt (CIrredEvCan { cc_ty = ty }) = tyVarsOfType ty
tyVarsOfCt (CNonCanonical { cc_ev = fl }) = tyVarsOfType (ctEvPred fl)
diff --git a/compiler/typecheck/TcBinds.lhs b/compiler/typecheck/TcBinds.lhs
index aa319c8b36..5eb8e150ef 100644
--- a/compiler/typecheck/TcBinds.lhs
+++ b/compiler/typecheck/TcBinds.lhs
@@ -45,6 +45,9 @@ import Util
import BasicTypes
import Outputable
import FastString
+import Type(mkStrLitTy)
+import Class(classTyCon)
+import PrelNames(ipClassName)
import Control.Monad
@@ -207,7 +210,9 @@ tcLocalBinds (HsValBinds (ValBindsOut binds sigs)) thing_inside
tcLocalBinds (HsValBinds (ValBindsIn {})) _ = panic "tcLocalBinds"
tcLocalBinds (HsIPBinds (IPBinds ip_binds _)) thing_inside
- = do { (given_ips, ip_binds') <- mapAndUnzipM (wrapLocSndM tc_ip_bind) ip_binds
+ = do { ipClass <- tcLookupClass ipClassName
+ ; (given_ips, ip_binds') <-
+ mapAndUnzipM (wrapLocSndM (tc_ip_bind ipClass)) ip_binds
-- If the binding binds ?x = E, we must now
-- discharge any ?x constraints in expr_lie
@@ -217,16 +222,28 @@ tcLocalBinds (HsIPBinds (IPBinds ip_binds _)) thing_inside
; return (HsIPBinds (IPBinds ip_binds' ev_binds), result) }
where
- ips = [ip | L _ (IPBind ip _) <- ip_binds]
+ ips = [ip | L _ (IPBind (Left ip) _) <- ip_binds]
-- I wonder if we should do these one at at time
-- Consider ?x = 4
-- ?y = ?x + 1
- tc_ip_bind (IPBind ip expr)
+ tc_ip_bind ipClass (IPBind (Left ip) expr)
= do { ty <- newFlexiTyVarTy openTypeKind
- ; ip_id <- newIP ip ty
+ ; let p = mkStrLitTy $ hsIPNameFS ip
+ ; ip_id <- newDict ipClass [ p, ty ]
; expr' <- tcMonoExpr expr ty
- ; return (ip_id, (IPBind (IPName ip_id) expr')) }
+ ; let d = toDict ipClass p ty `fmap` expr'
+ ; return (ip_id, (IPBind (Right ip_id) d)) }
+ tc_ip_bind _ (IPBind (Right {}) _) = panic "tc_ip_bind"
+
+ -- Coerces a `t` into a dictionry for `IP "x" t`.
+ -- co : t -> IP "x" t
+ toDict ipClass x ty =
+ case unwrapNewTyCon_maybe (classTyCon ipClass) of
+ Just (_,_,ax) -> HsWrap $ WpCast $ mkTcSymCo $ mkTcAxInstCo ax [x,ty]
+ Nothing -> panic "The dictionary for `IP` is not a newtype?"
+
+
\end{code}
Note [Implicit parameter untouchables]
diff --git a/compiler/typecheck/TcCanonical.lhs b/compiler/typecheck/TcCanonical.lhs
index 4beb6d2d9c..284d0218f5 100644
--- a/compiler/typecheck/TcCanonical.lhs
+++ b/compiler/typecheck/TcCanonical.lhs
@@ -14,7 +14,6 @@ module TcCanonical(
#include "HsVersions.h"
-import BasicTypes ( IPName )
import TcRnTypes
import TcType
import Type
@@ -23,7 +22,6 @@ import TcEvidence
import Class
import TyCon
import TypeRep
-import Name ( Name )
import Var
import VarEnv
import Outputable
@@ -199,11 +197,6 @@ canonicalize (CFunEqCan { cc_depth = d
= {-# SCC "canEqLeafFunEqLeftRec" #-}
canEqLeafFunEqLeftRec d fl (fn,xis1) xi2
-canonicalize (CIPCan { cc_depth = d
- , cc_ev = fl
- , cc_ip_nm = nm
- , cc_ip_ty = xi })
- = canIP d fl nm xi
canonicalize (CIrredEvCan { cc_ev = fl
, cc_depth = d
, cc_ty = xi })
@@ -219,7 +212,6 @@ canEvVar d fl pred_classifier
= case pred_classifier of
ClassPred cls tys -> canClassNC d fl cls tys
EqPred ty1 ty2 -> canEqNC d fl ty1 ty2
- IPPred nm ty -> canIP d fl nm ty
IrredPred ev_ty -> canIrred d fl ev_ty
TuplePred tys -> canTuple d fl tys
\end{code}
@@ -248,43 +240,6 @@ canTuple d fl tys
%************************************************************************
%* *
-%* Implicit Parameter Canonicalization
-%* *
-%************************************************************************
-
-\begin{code}
-canIP :: SubGoalDepth -- Depth
- -> CtEvidence
- -> IPName Name -> Type -> TcS StopOrContinue
--- Precondition: EvVar is implicit parameter evidence
-canIP d fl nm ty
- = -- Note [Canonical implicit parameter constraints] explains why it's
- -- possible in principle to not flatten, but since flattening applies
- -- the inert substitution we choose to flatten anyway.
- do { (xi,co) <- flatten d FMFullFlatten fl (mkIPPred nm ty)
- ; mb <- rewriteCtFlavor fl xi co
- ; case mb of
- Just new_fl -> let IPPred _ xi_in = classifyPredType xi
- in continueWith $ CIPCan { cc_ev = new_fl
- , cc_ip_nm = nm, cc_ip_ty = xi_in
- , cc_depth = d }
- Nothing -> return Stop }
-
-\end{code}
-
-Note [Canonical implicit parameter constraints]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The type in a canonical implicit parameter constraint doesn't need to
-be a xi (type-function-free type) since we can defer the flattening
-until checking this type for equality with another type. If we
-encounter two IP constraints with the same name, they MUST have the
-same type, and at that point we can generate a flattened equality
-constraint between the types. (On the other hand, the types in two
-class constraints for the same class MAY be equal, so they need to be
-flattened in the first place to facilitate comparing them.)
-
-%************************************************************************
-%* *
%* Class Canonicalization
%* *
%************************************************************************
@@ -441,7 +396,6 @@ is_improvement_pty ty = go (classifyPredType ty)
go (EqPred {}) = True
go (ClassPred cls _tys) = not $ null fundeps
where (_,fundeps) = classTvsFds cls
- go (IPPred {}) = False
go (TuplePred ts) = any is_improvement_pty ts
go (IrredPred {}) = True -- Might have equalities after reduction?
\end{code}
diff --git a/compiler/typecheck/TcErrors.lhs b/compiler/typecheck/TcErrors.lhs
index c46d826e0a..ff774fa37b 100644
--- a/compiler/typecheck/TcErrors.lhs
+++ b/compiler/typecheck/TcErrors.lhs
@@ -255,9 +255,10 @@ tryReporters reporters deflt cts
mkFlatErr :: ReportErrCtxt -> Ct -> TcM ErrMsg
-- Context is already set
mkFlatErr ctxt ct -- The constraint is always wanted
+ | isIPPred (ctPred ct) = mkIPErr ctxt [ct]
+ | otherwise
= case classifyPredType (ctPred ct) of
ClassPred {} -> mkDictErr ctxt [ct]
- IPPred {} -> mkIPErr ctxt [ct]
IrredPred {} -> mkIrredErr ctxt [ct]
EqPred {} -> mkEqErr1 ctxt ct
TuplePred {} -> panic "mkFlat"
@@ -289,9 +290,10 @@ reportFlatErrs ctxt cts
go [] dicts ips irreds
= (dicts, ips, irreds)
go (ct:cts) dicts ips irreds
+ | isIPPred (ctPred ct) = go cts dicts (ct:ips) irreds
+ | otherwise
= case classifyPredType (ctPred ct) of
ClassPred {} -> go cts (ct:dicts) ips irreds
- IPPred {} -> go cts dicts (ct:ips) irreds
IrredPred {} -> go cts dicts ips (ct:irreds)
_ -> panic "mkFlat"
-- TuplePreds should have been expanded away by the constraint
diff --git a/compiler/typecheck/TcExpr.lhs b/compiler/typecheck/TcExpr.lhs
index c915b16c42..f3c238bd66 100644
--- a/compiler/typecheck/TcExpr.lhs
+++ b/compiler/typecheck/TcExpr.lhs
@@ -63,6 +63,7 @@ import ErrUtils
import Outputable
import FastString
import Control.Monad
+import Class(classTyCon)
\end{code}
%************************************************************************
@@ -178,15 +179,23 @@ tcExpr (NegApp expr neg_expr) res_ty
; expr' <- tcMonoExpr expr res_ty
; return (NegApp expr' neg_expr') }
-tcExpr (HsIPVar ip) res_ty
- = do { let origin = IPOccOrigin ip
- -- Implicit parameters must have a *tau-type* not a
- -- type scheme. We enforce this by creating a fresh
- -- type variable as its type. (Because res_ty may not
- -- be a tau-type.)
- ; ip_ty <- newFlexiTyVarTy openTypeKind
- ; ip_var <- emitWanted origin (mkIPPred ip ip_ty)
- ; tcWrapResult (HsIPVar (IPName ip_var)) ip_ty res_ty }
+tcExpr (HsIPVar x) res_ty
+ = do { let origin = IPOccOrigin x
+ ; ipClass <- tcLookupClass ipClassName
+ {- Implicit parameters must have a *tau-type* not a.
+ type scheme. We enforce this by creating a fresh
+ type variable as its type. (Because res_ty may not
+ be a tau-type.) -}
+ ; ip_ty <- newFlexiTyVarTy openTypeKind
+ ; let ip_name = mkStrLitTy (hsIPNameFS x)
+ ; ip_var <- emitWanted origin (mkClassPred ipClass [ip_name, ip_ty])
+ ; tcWrapResult (fromDict ipClass ip_name ip_ty (HsVar ip_var)) ip_ty res_ty }
+ where
+ -- Coerces a dictionry for `IP "x" t` into `t`.
+ fromDict ipClass x ty =
+ case unwrapNewTyCon_maybe (classTyCon ipClass) of
+ Just (_,_,ax) -> HsWrap $ WpCast $ mkTcAxInstCo ax [x,ty]
+ Nothing -> panic "The dictionary for `IP` is not a newtype?"
tcExpr (HsLam match) res_ty
= do { (co_fn, match') <- tcMatchLambda match res_ty
diff --git a/compiler/typecheck/TcHsSyn.lhs b/compiler/typecheck/TcHsSyn.lhs
index a026c4381c..aa444715b0 100644
--- a/compiler/typecheck/TcHsSyn.lhs
+++ b/compiler/typecheck/TcHsSyn.lhs
@@ -359,7 +359,7 @@ zonkLocalBinds env (HsValBinds vb@(ValBindsOut binds sigs))
zonkLocalBinds env (HsIPBinds (IPBinds binds dict_binds))
= mappM (wrapLocM zonk_ip_bind) binds `thenM` \ new_binds ->
let
- env1 = extendIdZonkEnv env [ipNameName n | L _ (IPBind n _) <- new_binds]
+ env1 = extendIdZonkEnv env [ n | L _ (IPBind (Right n) _) <- new_binds]
in
zonkTcEvBinds env1 dict_binds `thenM` \ (env2, new_dict_binds) ->
returnM (env2, HsIPBinds (IPBinds new_binds new_dict_binds))
@@ -539,8 +539,8 @@ zonkLExpr env expr = wrapLocM (zonkExpr env) expr
zonkExpr env (HsVar id)
= returnM (HsVar (zonkIdOcc env id))
-zonkExpr env (HsIPVar id)
- = returnM (HsIPVar (mapIPName (zonkIdOcc env) id))
+zonkExpr _ (HsIPVar id)
+ = returnM (HsIPVar id)
zonkExpr env (HsLit (HsRat f ty))
= zonkTcTypeToType env ty `thenM` \ new_ty ->
@@ -862,8 +862,9 @@ zonkRecFields env (HsRecFields flds dd)
; return (fld { hsRecFieldId = new_id, hsRecFieldArg = new_expr }) }
-------------------------------------------------------------------------
-mapIPNameTc :: (a -> TcM b) -> IPName a -> TcM (IPName b)
-mapIPNameTc f (IPName n) = f n `thenM` \ r -> returnM (IPName r)
+mapIPNameTc :: (a -> TcM b) -> Either HsIPName a -> TcM (Either HsIPName b)
+mapIPNameTc _ (Left x) = returnM (Left x)
+mapIPNameTc f (Right x) = f x `thenM` \ r -> returnM (Right r)
\end{code}
diff --git a/compiler/typecheck/TcHsType.lhs b/compiler/typecheck/TcHsType.lhs
index 2a1f4f3540..7808c6b44c 100644
--- a/compiler/typecheck/TcHsType.lhs
+++ b/compiler/typecheck/TcHsType.lhs
@@ -76,6 +76,7 @@ import FastString
import Util
import Control.Monad ( unless, when, zipWithM )
+import PrelNames(ipClassName)
\end{code}
@@ -422,7 +423,10 @@ tc_hs_type ipTy@(HsIParamTy n ty) exp_kind
= do { ty' <- tc_lhs_type ty
(EK liftedTypeKind (ptext (sLit "The type argument of the implicit parameter had")))
; checkExpectedKind ipTy constraintKind exp_kind
- ; return (mkIPPred n ty') }
+ ; ipClass <- tcLookupClass ipClassName
+ ; let n' = mkStrLitTy $ hsIPNameFS n
+ ; return (mkClassPred ipClass [n',ty'])
+ }
tc_hs_type ty@(HsEqTy ty1 ty2) exp_kind
= do { (ty1', kind1) <- tc_infer_lhs_type ty1
diff --git a/compiler/typecheck/TcInteract.lhs b/compiler/typecheck/TcInteract.lhs
index 9aa5730856..adff5ea182 100644
--- a/compiler/typecheck/TcInteract.lhs
+++ b/compiler/typecheck/TcInteract.lhs
@@ -29,7 +29,6 @@ import PrelNames (singIClassName)
import Class
import TyCon
import Name
-import IParam
import FunDeps
@@ -276,9 +275,6 @@ Case 1: In Rewriting Equalities (function rewriteEqLHS)
Case 2: Functional Dependencies
Again, we should prefer, if possible, the inert variables on the RHS
-Case 3: IP improvement work
- We must always rewrite so that the inert type is on the right.
-
\begin{code}
spontaneousSolveStage :: SimplifierStage
spontaneousSolveStage workItem
@@ -378,14 +374,12 @@ kick_out_rewritable ct is@(IS { inert_cans =
IC { inert_eqs = eqmap
, inert_eq_tvs = inscope
, inert_dicts = dictmap
- , inert_ips = ipmap
, inert_funeqs = funeqmap
, inert_irreds = irreds }
, inert_frozen = frozen })
= ((kicked_out,eqmap), remaining)
where
- rest_out = fro_out `andCts` dicts_out
- `andCts` ips_out `andCts` irs_out
+ rest_out = fro_out `andCts` dicts_out `andCts` irs_out
kicked_out = WorkList { wl_eqs = []
, wl_funeqs = bagToList feqs_out
, wl_rest = bagToList rest_out }
@@ -394,7 +388,6 @@ kick_out_rewritable ct is@(IS { inert_cans =
, inert_eq_tvs = inscope
-- keep the same, safe and cheap
, inert_dicts = dicts_in
- , inert_ips = ips_in
, inert_funeqs = feqs_in
, inert_irreds = irs_in }
, inert_frozen = fro_in }
@@ -404,8 +397,6 @@ kick_out_rewritable ct is@(IS { inert_cans =
-- subsitution into account
fl = cc_ev ct
tv = cc_tyvar ct
-
- (ips_out, ips_in) = partitionCCanMap rewritable ipmap
(feqs_out, feqs_in) = partCtFamHeadMap rewritable funeqmap
(dicts_out, dicts_in) = partitionCCanMap rewritable dictmap
@@ -635,6 +626,8 @@ solveWithIdentity d wd tv xi
* *
*********************************************************************************
+Note [
+
Note [The Solver Invariant]
~~~~~~~~~~~~~~~~~~~~~~~~~~~
We always add Givens first. So you might think that the solver has
@@ -722,7 +715,7 @@ interactWithInertsStage wi
doInteractWithInert :: Ct -> Ct -> TcS InteractResult
-- Identical class constraints.
doInteractWithInert
- inertItem@(CDictCan { cc_ev = fl1, cc_class = cls1, cc_tyargs = tys1 })
+ inertItem@(CDictCan { cc_ev = fl1, cc_class = cls1, cc_tyargs = tys1 })
workItem@(CDictCan { cc_ev = fl2, cc_class = cls2, cc_tyargs = tys2 })
| cls1 == cls2
@@ -766,46 +759,6 @@ doInteractWithInert (CIrredEvCan { cc_ev = ifl, cc_ty = ty1 })
| ty1 `eqType` ty2
= solveOneFromTheOther "Irred/Irred" ifl workItem
--- Two implicit parameter constraints. If the names are the same,
--- but their types are not, we generate a wanted type equality
--- that equates the type (this is "improvement").
--- However, we don't actually need the coercion evidence,
--- so we just generate a fresh coercion variable that isn't used anywhere.
-doInteractWithInert (CIPCan { cc_ev = ifl, cc_ip_nm = nm1, cc_ip_ty = ty1 })
- workItem@(CIPCan { cc_ev = wfl, cc_ip_nm = nm2, cc_ip_ty = ty2 })
- | nm1 == nm2 && isGiven wfl && isGiven ifl
- = -- See Note [Overriding implicit parameters]
- -- Dump the inert item, override totally with the new one
- -- Do not require type equality
- -- For example, given let ?x::Int = 3 in let ?x::Bool = True in ...
- -- we must *override* the outer one with the inner one
- irInertConsumed "IP/IP (override inert)"
-
- | nm1 == nm2 && ty1 `eqType` ty2
- = solveOneFromTheOther "IP/IP" ifl workItem
-
- | nm1 == nm2
- = -- See Note [When improvement happens]
- do { mb_eqv <- newWantedEvVar new_wloc (mkEqPred ty2 ty1)
- -- co :: ty2 ~ ty1, see Note [Efficient orientation]
- ; cv <- case mb_eqv of
- Fresh eqv ->
- do { updWorkListTcS $ extendWorkListEq $
- CNonCanonical { cc_ev = eqv
- , cc_depth = cc_depth workItem }
- ; return (ctEvTerm eqv) }
- Cached eqv -> return eqv
- ; case wfl of
- Wanted { ctev_evar = ev_id } ->
- let ip_co = mkTcTyConAppCo (ipTyCon nm1) [evTermCoercion cv]
- in do { setEvBind ev_id $
- mkEvCast (ctEvTerm ifl) (mkTcSymCo ip_co)
- ; irWorkItemConsumed "IP/IP (solved by rewriting)" }
- _ -> pprPanic "Unexpected IP constraint" (ppr workItem) }
- where
- new_wloc | isGiven wfl = getWantedLoc ifl
- | otherwise = getWantedLoc wfl
-
doInteractWithInert ii@(CFunEqCan { cc_ev = fl1, cc_fun = tc1
, cc_tyargs = args1, cc_rhs = xi1, cc_depth = d1 })
wi@(CFunEqCan { cc_ev = fl2, cc_fun = tc2
@@ -873,6 +826,65 @@ doInteractWithInert _ _ = irKeepGoing "NOP"
\end{code}
+
+Note [Shadowing of Implicit Parameters]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Consider the following example:
+
+f :: (?x :: Char) => Char
+f = let ?x = 'a' in ?x
+
+The "let ?x = ..." generates an implication constraint of the form:
+
+?x :: Char => ?x :: Char
+
+Furthermore, the signature for `f` also generates an implication
+constraint, so we end up with the following nested implication:
+
+?x :: Char => (?x :: Char => ?x :: Char)
+
+Note that the wanted (?x :: Char) constraint may be solved in
+two incompatible ways: either by using the parameter from the
+signature, or by using the local definition. Our intention is
+that the local definition should "shadow" the parameter of the
+signature, and we implement this as follows: when we add a new
+given implicit parameter to the inert set, it replaces any existing
+givens for the same implicit parameter.
+
+This works for the normal cases but it has an odd side effect
+in some pathological programs like this:
+
+-- This is accepted, the second parameter shadows
+f1 :: (?x :: Int, ?x :: Char) => Char
+f1 = ?x
+
+-- This is rejected, the second parameter shadows
+f2 :: (?x :: Int, ?x :: Char) => Int
+f2 = ?x
+
+Both of these are actually wrong: when we try to use either one,
+we'll get two incompatible wnated constraints (?x :: Int, ?x :: Char),
+which would lead to an error.
+
+I can think of two ways to fix this:
+
+ 1. Simply disallow multiple constratits for the same implicit
+ parameter---this is never useful, and it can be detected completely
+ syntactically.
+
+ 2. Move the shadowing machinery to the location where we nest
+ implications, and add some code here that will produce an
+ error if we get multiple givens for the same implicit parameter.
+
+
+
+
+
+
+
+
+
Note [Cache-caused loops]
~~~~~~~~~~~~~~~~~~~~~~~~~
It is very dangerous to cache a rewritten wanted family equation as 'solved' in our
diff --git a/compiler/typecheck/TcMType.lhs b/compiler/typecheck/TcMType.lhs
index 7404acd58c..4e6f499db1 100644
--- a/compiler/typecheck/TcMType.lhs
+++ b/compiler/typecheck/TcMType.lhs
@@ -33,7 +33,7 @@ module TcMType (
--------------------------------
-- Creating new evidence variables
newEvVar, newEvVars,
- newEq, newIP, newDict,
+ newEq, newDict,
newWantedEvVar, newWantedEvVars,
newTcEvBinds, addTcEvBind,
@@ -85,7 +85,6 @@ import Var
-- others:
import HsSyn -- HsType
import TcRnMonad -- TcType, amongst others
-import IParam
import Id
import FunDeps
import Name
@@ -95,7 +94,6 @@ import DynFlags
import Util
import Maybes
import ListSetOps
-import BasicTypes
import SrcLoc
import Outputable
import FastString
@@ -156,11 +154,6 @@ newEq ty1 ty2
= do { name <- newName (mkVarOccFS (fsLit "cobox"))
; return (mkLocalId name (mkTcEqPred ty1 ty2)) }
-newIP :: IPName Name -> TcType -> TcM IpId
-newIP ip ty
- = do { name <- newName (mkVarOccFS (ipFastString ip))
- ; return (mkLocalId name (mkIPPred ip ty)) }
-
newDict :: Class -> [TcType] -> TcM DictId
newDict cls tys
= do { name <- newName (mkDictOcc (getOccName cls))
@@ -169,7 +162,6 @@ newDict cls tys
predTypeOccName :: PredType -> OccName
predTypeOccName ty = case classifyPredType ty of
ClassPred cls _ -> mkDictOcc (getOccName cls)
- IPPred ip _ -> mkVarOccFS (ipFastString ip)
EqPred _ _ -> mkVarOccFS (fsLit "cobox")
TuplePred _ -> mkVarOccFS (fsLit "tup")
IrredPred _ -> mkVarOccFS (fsLit "irred")
@@ -1186,19 +1178,6 @@ check_pred_ty' dflags _ctxt (EqPred ty1 ty2)
; checkValidMonoType ty2
}
-check_pred_ty' _ _ctxt (IPPred _ ty) = checkValidMonoType ty
- -- Contrary to GHC 7.2 and below, we allow implicit parameters not only
- -- in type signatures but also in instance decls, superclasses etc
- -- The reason we didn't allow implicit params in instances is a bit
- -- subtle:
- -- If we allowed instance (?x::Int, Eq a) => Foo [a] where ...
- -- then when we saw (e :: (?x::Int) => t) it would be unclear how to
- -- discharge all the potential usas of the ?x in e. For example, a
- -- constraint Foo [Int] might come out of e,and applying the
- -- instance decl would show up two uses of ?x.
- --
- -- Happily this is not an issue in the new constraint solver.
-
check_pred_ty' dflags ctxt t@(TuplePred ts)
= do { checkTc (xopt Opt_ConstraintKinds dflags)
(predTupleErr (predTreePredType t))
@@ -1759,17 +1738,22 @@ sizeTypes xs = sum (map sizeType tys)
-- Size of a predicate
--
--- We are considering whether *class* constraints terminate
--- Once we get into an implicit parameter or equality we
--- can't get back to a class constraint, so it's safe
--- to say "size 0". See Trac #4200.
+-- We are considering whether class constraints terminate.
+-- Equality constraints and constraints for the implicit
+-- parameter class always termiante so it is safe to say "size 0".
+-- (Implicit parameter constraints always terminate because
+-- there are no instances for them---they are only solved by
+-- "local instances" in expressions).
+-- See Trac #4200.
sizePred :: PredType -> Int
-sizePred ty = go (classifyPredType ty)
+sizePred ty = goClass ty
where
+ goClass p | isIPPred p = 0
+ | otherwise = go (classifyPredType p)
+
go (ClassPred _ tys') = sizeTypes tys'
- go (IPPred {}) = 0
go (EqPred {}) = 0
- go (TuplePred ts) = sum (map (go . classifyPredType) ts)
+ go (TuplePred ts) = sum (map goClass ts)
go (IrredPred ty) = sizeType ty
\end{code}
diff --git a/compiler/typecheck/TcRnTypes.lhs b/compiler/typecheck/TcRnTypes.lhs
index 2c8d69e2f6..1ed3d0d198 100644
--- a/compiler/typecheck/TcRnTypes.lhs
+++ b/compiler/typecheck/TcRnTypes.lhs
@@ -53,7 +53,7 @@ module TcRnTypes(
-- Canonical constraints
Xi, Ct(..), Cts, emptyCts, andCts, andManyCts, keepWanted,
singleCt, extendCts, isEmptyCts, isCTyEqCan, isCFunEqCan,
- isCDictCan_Maybe, isCIPCan_Maybe, isCFunEqCan_Maybe,
+ isCDictCan_Maybe, isCFunEqCan_Maybe,
isCIrredEvCan, isCNonCanonical, isWantedCt, isDerivedCt,
isGivenCt,
ctWantedLoc, ctEvidence,
@@ -847,19 +847,11 @@ data Ct
-- See Note [WorkList]
}
- | CIPCan { -- ?x::tau
- -- See note [Canonical implicit parameter constraints].
- cc_ev :: CtEvidence,
- cc_ip_nm :: IPName Name,
- cc_ip_ty :: TcTauType, -- Not a Xi! See same not as above
- cc_depth :: SubGoalDepth -- See Note [WorkList]
- }
-
| CIrredEvCan { -- These stand for yet-unknown predicates
cc_ev :: CtEvidence,
cc_ty :: Xi, -- cc_ty is flat hence it may only be of the form (tv xi1 xi2 ... xin)
-- Since, if it were a type constructor application, that'd make the
- -- whole constraint a CDictCan, CIPCan, or CTyEqCan. And it can't be
+ -- whole constraint a CDictCan, or CTyEqCan. And it can't be
-- a type family application either because it's a Xi type.
cc_depth :: SubGoalDepth -- See Note [WorkList]
}
@@ -922,8 +914,6 @@ ctPred (CTyEqCan { cc_tyvar = tv, cc_rhs = xi })
= mkTcEqPred (mkTyVarTy tv) xi
ctPred (CFunEqCan { cc_fun = fn, cc_tyargs = xis1, cc_rhs = xi2 })
= mkTcEqPred (mkTyConApp fn xis1) xi2
-ctPred (CIPCan { cc_ip_nm = nm, cc_ip_ty = xi })
- = mkIPPred nm xi
ctPred (CIrredEvCan { cc_ty = xi }) = xi
-}
\end{code}
@@ -960,10 +950,6 @@ isCDictCan_Maybe :: Ct -> Maybe Class
isCDictCan_Maybe (CDictCan {cc_class = cls }) = Just cls
isCDictCan_Maybe _ = Nothing
-isCIPCan_Maybe :: Ct -> Maybe (IPName Name)
-isCIPCan_Maybe (CIPCan {cc_ip_nm = nm }) = Just nm
-isCIPCan_Maybe _ = Nothing
-
isCIrredEvCan :: Ct -> Bool
isCIrredEvCan (CIrredEvCan {}) = True
isCIrredEvCan _ = False
@@ -990,7 +976,6 @@ instance Outputable Ct where
CFunEqCan {} -> "CFunEqCan"
CNonCanonical {} -> "CNonCanonical"
CDictCan {} -> "CDictCan"
- CIPCan {} -> "CIPCan"
CIrredEvCan {} -> "CIrredEvCan"
\end{code}
@@ -1397,7 +1382,7 @@ data SkolemInfo
| ArrowSkol -- An arrow form (see TcArrows)
- | IPSkol [IPName Name] -- Binding site of an implicit parameter
+ | IPSkol [HsIPName] -- Binding site of an implicit parameter
| RuleSkol RuleName -- The LHS of a RULE
@@ -1465,7 +1450,7 @@ data CtOrigin
| TypeEqOrigin EqOrigin
- | IPOccOrigin (IPName Name) -- Occurrence of an implicit parameter
+ | IPOccOrigin HsIPName -- Occurrence of an implicit parameter
| LiteralOrigin (HsOverLit Name) -- Occurrence of a literal
| NegateOrigin -- Occurrence of syntactic negation
diff --git a/compiler/typecheck/TcSMonad.lhs b/compiler/typecheck/TcSMonad.lhs
index c4ceaea050..f0c69c5819 100644
--- a/compiler/typecheck/TcSMonad.lhs
+++ b/compiler/typecheck/TcSMonad.lhs
@@ -73,7 +73,7 @@ module TcSMonad (
CCanMap(..), CtTypeMap, CtFamHeadMap, CtPredMap,
PredMap, FamHeadMap,
partCtFamHeadMap, lookupFamHead,
-
+ filterSolved,
instDFunType, -- Instantiation
newFlexiTcSTy, instFlexiTcS,
@@ -99,7 +99,6 @@ module TcSMonad (
#include "HsVersions.h"
import HscTypes
-import BasicTypes
import Inst
import InstEnv
@@ -399,6 +398,11 @@ partCtFamHeadMap f ctmap
= ty1
| otherwise
= panic "partCtFamHeadMap, encountered non equality!"
+
+filterSolved :: (CtEvidence -> Bool) -> PredMap CtEvidence -> PredMap CtEvidence
+filterSolved p (PredMap mp) = PredMap (foldTM upd mp emptyTM)
+ where upd a m = if p a then alterTM (ctEvPred a) (\_ -> Just a) m
+ else m
\end{code}
%************************************************************************
@@ -423,10 +427,6 @@ data InertCans
-- Dictionaries only, index is the class
-- NB: index is /not/ the whole type because FD reactions
-- need to match the class but not necessarily the whole type.
- , inert_ips :: CCanMap (IPName Name)
- -- Implicit parameters, index is the name
- -- NB: index is /not/ the whole type because IP reactions need
- -- to match the ip name but not necessarily the whole type.
, inert_funeqs :: CtFamHeadMap
-- Family equations, index is the whole family head type.
, inert_irreds :: Cts
@@ -525,7 +525,6 @@ data InertSet
instance Outputable InertCans where
ppr ics = vcat [ vcat (map ppr (varEnvElts (inert_eqs ics)))
, vcat (map ppr (Bag.bagToList $ cCanMapToBag (inert_dicts ics)))
- , vcat (map ppr (Bag.bagToList $ cCanMapToBag (inert_ips ics)))
, vcat (map ppr (Bag.bagToList $
ctTypeMapCts (unFamHeadMap $ inert_funeqs ics)))
, vcat (map ppr (Bag.bagToList $ inert_irreds ics))
@@ -545,7 +544,6 @@ emptyInert
= IS { inert_cans = IC { inert_eqs = emptyVarEnv
, inert_eq_tvs = emptyInScopeSet
, inert_dicts = emptyCCanMap
- , inert_ips = emptyCCanMap
, inert_funeqs = FamHeadMap emptyTM
, inert_irreds = emptyCts }
, inert_frozen = emptyCts
@@ -592,9 +590,6 @@ updInertSet is item
in ics { inert_eqs = eqs', inert_eq_tvs = inscope' }
- | Just x <- isCIPCan_Maybe item -- IP
- = ics { inert_ips = updCCanMap (x,item) (inert_ips ics) }
-
| isCIrredEvCan item -- Presently-irreducible evidence
= ics { inert_irreds = inert_irreds ics `Bag.snocBag` item }
@@ -683,7 +678,6 @@ extractUnsolved :: InertSet -> ((Cts,Cts), InertSet)
extractUnsolved (IS { inert_cans = IC { inert_eqs = eqs
, inert_eq_tvs = eq_tvs
, inert_irreds = irreds
- , inert_ips = ips
, inert_funeqs = funeqs
, inert_dicts = dicts
}
@@ -696,7 +690,6 @@ extractUnsolved (IS { inert_cans = IC { inert_eqs = eqs
= let is_solved = IS { inert_cans = IC { inert_eqs = solved_eqs
, inert_eq_tvs = eq_tvs
, inert_dicts = solved_dicts
- , inert_ips = solved_ips
, inert_irreds = solved_irreds
, inert_funeqs = solved_funeqs }
, inert_frozen = emptyCts -- All out
@@ -715,12 +708,11 @@ extractUnsolved (IS { inert_cans = IC { inert_eqs = eqs
eqs `minusVarEnv` solved_eqs
(unsolved_irreds, solved_irreds) = Bag.partitionBag (not.isGivenCt) irreds
- (unsolved_ips, solved_ips) = extractUnsolvedCMap ips
(unsolved_dicts, solved_dicts) = extractUnsolvedCMap dicts
(unsolved_funeqs, solved_funeqs) = partCtFamHeadMap (not . isGivenCt) funeqs
unsolved = unsolved_eqs `unionBags` unsolved_irreds `unionBags`
- unsolved_ips `unionBags` unsolved_dicts `unionBags` unsolved_funeqs
+ unsolved_dicts `unionBags` unsolved_funeqs
@@ -749,9 +741,6 @@ extractRelevantInerts wi
Nothing -> (emptyCts, funeq_map)
Just ct -> (singleCt ct, new_funeq_map)
in (cts, ics { inert_funeqs = FamHeadMap feqs_map })
- extract_ics_relevants (CIPCan { cc_ip_nm = nm } ) ics =
- let (cts, ips_map) = getRelevantCts nm (inert_ips ics)
- in (cts, ics { inert_ips = ips_map })
extract_ics_relevants (CIrredEvCan { }) ics =
let cts = inert_irreds ics
in (cts, ics { inert_irreds = emptyCts })
diff --git a/compiler/typecheck/TcSimplify.lhs b/compiler/typecheck/TcSimplify.lhs
index 34c40f2a63..39f7f4d72a 100644
--- a/compiler/typecheck/TcSimplify.lhs
+++ b/compiler/typecheck/TcSimplify.lhs
@@ -22,7 +22,7 @@ import TcSMonad
import TcInteract
import Inst
import Unify ( niFixTvSubst, niSubstTvSet )
-import Type ( classifyPredType, PredTree(..) )
+import Type ( classifyPredType, PredTree(..), isIPPred_maybe )
import Var
import Unique
import VarSet
@@ -42,7 +42,7 @@ import Outputable
import FastString
import TrieMap () -- DV: for now
import DynFlags
-
+import Data.Maybe ( mapMaybe )
\end{code}
@@ -965,7 +965,8 @@ solveImplication tcs_untouchables
, ic_given = givens
, ic_wanted = wanteds
, ic_loc = loc })
- = nestImplicTcS ev_binds (untch, tcs_untouchables) $
+ = shadowIPs givens $ -- See Note [Shadowing of Implicit Parameters]
+ nestImplicTcS ev_binds (untch, tcs_untouchables) $
recoverTcS (return (emptyBag, emptyBag)) $
-- Recover from nested failures. Even the top level is
-- just a bunch of implications, so failing at the first one is bad
@@ -1039,6 +1040,31 @@ floatEqualities skols can_given wantders
inner_tvs `unionVarSet` tvs_under_fsks (tyVarKind tv)
where
inner_tvs = tvs_under_fsks ty
+
+shadowIPs :: [EvVar] -> TcS a -> TcS a
+shadowIPs gs m
+ | null shadowed = m
+ | otherwise = do is <- getTcSInerts
+ doWithInert (purgeShadowed is) m
+ where
+ shadowed = mapMaybe isIP gs
+
+ isIP g = do p <- evVarPred_maybe g
+ (x,_) <- isIPPred_maybe p
+ return x
+
+ isShadowedCt ct = isShadowedEv (ctEvidence ct)
+ isShadowedEv ev = case isIPPred_maybe (ctEvPred ev) of
+ Just (x,_) -> x `elem` shadowed
+ _ -> False
+
+ purgeShadowed is = is { inert_cans = purgeCans (inert_cans is)
+ , inert_solved = purgeSolved (inert_solved is)
+ }
+
+ purgeDicts = snd . partitionCCanMap isShadowedCt
+ purgeCans ics = ics { inert_dicts = purgeDicts (inert_dicts ics) }
+ purgeSolved = filterSolved (not . isShadowedEv)
\end{code}
Note [Preparing inert set for implications]
@@ -1241,6 +1267,39 @@ f (x::beta) =
g2 z = case z of TEx y -> (h [[undefined]], op x [y])
in (g1 '3', g2 undefined)
+Note [Shadowing of Implicit Parameters]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider the following example:
+
+f :: (?x :: Char) => Char
+f = let ?x = 'a' in ?x
+
+The "let ?x = ..." generates an implication constraint of the form:
+
+?x :: Char => ?x :: Char
+
+
+Furthermore, the signature for `f` also generates an implication
+constraint, so we end up with the following nested implication:
+
+?x :: Char => (?x :: Char => ?x :: Char)
+
+Note that the wanted (?x :: Char) constraint may be solved in
+two incompatible ways: either by using the parameter from the
+signature, or by using the local definition. Our intention is
+that the local definition should "shadow" the parameter of the
+signature, and we implement this as follows: when we nest implications,
+we remove any implicit parameters in the outer implication, that
+have the same name as givens of the inner implication.
+
+Here is another variation of the example:
+
+f :: (?x :: Int) => Char
+f = let ?x = 'x' in ?x
+
+This program should also be accepted: the two constraints `?x :: Int`
+and `?x :: Char` never exist in the same context, so they don't get to
+interact to cause failure.
\begin{code}
solveCTyFunEqs :: Cts -> TcS (TvSubst, Cts)
diff --git a/compiler/typecheck/TcSplice.lhs b/compiler/typecheck/TcSplice.lhs
index c02f885edf..fac61afe65 100644
--- a/compiler/typecheck/TcSplice.lhs
+++ b/compiler/typecheck/TcSplice.lhs
@@ -1424,10 +1424,14 @@ reify_tc_app tc tys
removeKinds _ tys = tys
reifyPred :: TypeRep.PredType -> TcM TH.Pred
-reifyPred ty = case classifyPredType ty of
+reifyPred ty
+ -- We could reify the implicit paramter as a class but it seems
+ -- nicer to support them properly...
+ | isIPPred ty = noTH (sLit "implicit parameters") (ppr ty)
+ | otherwise
+ = case classifyPredType ty of
ClassPred cls tys -> do { tys' <- reifyTypes tys
; return $ TH.ClassP (reifyName cls) tys' }
- IPPred _ _ -> noTH (sLit "implicit parameters") (ppr ty)
EqPred ty1 ty2 -> do { ty1' <- reifyType ty1
; ty2' <- reifyType ty2
; return $ TH.EqualP ty1' ty2'
diff --git a/compiler/typecheck/TcType.lhs b/compiler/typecheck/TcType.lhs
index effc30d946..5e050e5465 100644
--- a/compiler/typecheck/TcType.lhs
+++ b/compiler/typecheck/TcType.lhs
@@ -130,7 +130,7 @@ module TcType (
mkTyVarTy, mkTyVarTys, mkTyConTy,
isClassPred, isEqPred, isIPPred,
- mkClassPred, mkIPPred,
+ mkClassPred,
isDictLikeTy,
tcSplitDFunTy, tcSplitDFunHead,
mkEqPred,
@@ -1091,9 +1091,6 @@ shallowPredTypePredTree ev_ty
() | tc `hasKey` eqTyConKey
, let [_, ty1, ty2] = tys
-> EqPred ty1 ty2
- () | Just ip <- tyConIP_maybe tc
- , let [ty] = tys
- -> IPPred ip ty
() | isTupleTyCon tc
-> TuplePred tys
_ -> IrredPred ev_ty
diff --git a/compiler/types/IParam.lhs b/compiler/types/IParam.lhs
deleted file mode 100644
index 67d46c3a82..0000000000
--- a/compiler/types/IParam.lhs
+++ /dev/null
@@ -1,41 +0,0 @@
-%
-% (c) The University of Glasgow 2006
-% (c) The GRASP/AQUA Project, Glasgow University, 1998
-%
-
-\begin{code}
-module IParam (
- ipFastString, ipTyConName, ipTyCon, ipCoAxiom
- ) where
-
-#include "HsVersions.h"
-
-import Name
-import TyCon (CoAxiom, TyCon, newTyConCo_maybe)
-import Type
-
-import BasicTypes (IPName(..), ipNameName)
-import FastString
-import Outputable
-\end{code}
-
-\begin{code}
-ipFastString :: IPName Name -> FastString
-ipFastString = occNameFS . nameOccName . ipTyConName
-
-ipTyConName :: IPName Name -> Name
-ipTyConName = ipNameName
-
-ipTyCon :: IPName Name -> TyCon
-ipTyCon ip = case wiredInNameTyThing_maybe (ipTyConName ip) of
- Just (ATyCon tc) -> tc
- _ -> pprPanic "ipTyCon" (ppr ip)
-
-ipCoAxiom :: IPName Name -> CoAxiom
-ipCoAxiom ip = case newTyConCo_maybe (ipTyCon ip) of
- Just ax -> ax
- _ -> pprPanic "ipCoAxiom" (ppr ip)
-
--- The IParam DataCon never gets any code generated for it, so it's
--- a bit dangerous to actually make use of it, hence no ipDataCon function
-\end{code}
diff --git a/compiler/types/IParam.lhs-boot b/compiler/types/IParam.lhs-boot
deleted file mode 100644
index 34acf1a5da..0000000000
--- a/compiler/types/IParam.lhs-boot
+++ /dev/null
@@ -1,10 +0,0 @@
-\begin{code}
-module IParam where
-
-import Name
-import BasicTypes
-import {-# SOURCE #-} TyCon (TyCon)
-
-ipTyConName :: IPName Name -> Name
-ipTyCon :: IPName Name -> TyCon
-\end{code} \ No newline at end of file
diff --git a/compiler/types/TyCon.lhs b/compiler/types/TyCon.lhs
index 47db814476..c12947911b 100644
--- a/compiler/types/TyCon.lhs
+++ b/compiler/types/TyCon.lhs
@@ -64,7 +64,7 @@ module TyCon(
tyConStupidTheta,
tyConArity,
tyConParent,
- tyConTuple_maybe, tyConClass_maybe, tyConIP_maybe,
+ tyConTuple_maybe, tyConClass_maybe,
tyConFamInst_maybe, tyConFamInstSig_maybe, tyConFamilyCoercion_maybe,
synTyConDefn, synTyConRhs, synTyConType,
tyConExtName, -- External name for foreign types
@@ -89,7 +89,6 @@ module TyCon(
import {-# SOURCE #-} TypeRep ( Kind, Type, PredType )
import {-# SOURCE #-} DataCon ( DataCon, isVanillaDataCon )
-import {-# SOURCE #-} IParam ( ipTyConName )
import Var
import Class
@@ -514,10 +513,6 @@ data TyConParent
| ClassTyCon
Class -- INVARIANT: the classTyCon of this Class is the current tycon
- -- | Associated type of a implicit parameter.
- | IPTyCon
- (IPName Name)
-
-- | An *associated* type of a class.
| AssocFamilyTyCon
Class -- The class in whose declaration the family is declared
@@ -555,7 +550,6 @@ data TyConParent
instance Outputable TyConParent where
ppr NoParentTyCon = text "No parent"
ppr (ClassTyCon cls) = text "Class parent" <+> ppr cls
- ppr (IPTyCon n) = text "IP parent" <+> ppr n
ppr (AssocFamilyTyCon cls) = text "Class parent (assoc. family)" <+> ppr cls
ppr (FamInstTyCon _ tc tys) = text "Family parent (family instance)" <+> ppr tc <+> sep (map ppr tys)
@@ -564,7 +558,6 @@ okParent :: Name -> TyConParent -> Bool
okParent _ NoParentTyCon = True
okParent tc_name (AssocFamilyTyCon cls) = tc_name `elem` map tyConName (classATs cls)
okParent tc_name (ClassTyCon cls) = tc_name == tyConName (classTyCon cls)
-okParent tc_name (IPTyCon ip) = tc_name == ipTyConName ip
okParent _ (FamInstTyCon _ fam_tc tys) = tyConArity fam_tc == length tys
isNoParent :: TyConParent -> Bool
@@ -1409,12 +1402,6 @@ tyConTuple_maybe :: TyCon -> Maybe TupleSort
tyConTuple_maybe (TupleTyCon {tyConTupleSort = sort}) = Just sort
tyConTuple_maybe _ = Nothing
--- | If this 'TyCon' is that for implicit parameter, return the IP it is for.
--- Otherwise returns @Nothing@
-tyConIP_maybe :: TyCon -> Maybe (IPName Name)
-tyConIP_maybe (AlgTyCon {algTcParent = IPTyCon ip}) = Just ip
-tyConIP_maybe _ = Nothing
-
----------------------------------------------------------------------------
tyConParent :: TyCon -> TyConParent
tyConParent (AlgTyCon {algTcParent = parent}) = parent
diff --git a/compiler/types/Type.lhs b/compiler/types/Type.lhs
index 4726f26213..1099303e48 100644
--- a/compiler/types/Type.lhs
+++ b/compiler/types/Type.lhs
@@ -53,14 +53,12 @@ module Type (
isDictLikeTy,
mkEqPred, mkPrimEqPred,
mkClassPred,
- mkIPPred,
- noParenPred, isClassPred, isEqPred, isIPPred,
+ noParenPred, isClassPred, isEqPred, isIPPred, isIPPred_maybe,
-- Deconstructing predicate types
PredTree(..), predTreePredType, classifyPredType,
getClassPredTys, getClassPredTys_maybe,
getEqPredTys, getEqPredTys_maybe,
- getIPPredTy_maybe,
-- ** Common type constructors
funTyCon,
@@ -153,13 +151,11 @@ import Class
import TyCon
import TysPrim
import {-# SOURCE #-} TysWiredIn ( eqTyCon, mkBoxedTupleTy )
-import PrelNames ( eqTyConKey )
+import PrelNames ( eqTyConKey, ipClassName )
-- others
-import {-# SOURCE #-} IParam ( ipTyCon )
import Unique ( Unique, hasKey )
-import BasicTypes ( Arity, RepArity, IPName(..) )
-import Name ( Name )
+import BasicTypes ( Arity, RepArity )
import NameSet
import StaticFlags
import Util
@@ -169,6 +165,7 @@ import FastString
import Data.List ( partition )
import Maybes ( orElse )
import Data.Maybe ( isJust )
+import Control.Monad ( guard )
infixr 3 `mkFunTy` -- Associates to the right
\end{code}
@@ -840,7 +837,7 @@ noParenPred :: PredType -> Bool
-- C a => a -> a
-- a~b => a -> b
-- But (?x::Int) => Int -> Int
-noParenPred p = isClassPred p || isEqPred p
+noParenPred p = not (isIPPred p) && isClassPred p || isEqPred p
isPredTy :: Type -> Bool
isPredTy ty
@@ -857,9 +854,17 @@ isClassPred ty = case tyConAppTyCon_maybe ty of
isEqPred ty = case tyConAppTyCon_maybe ty of
Just tyCon -> tyCon `hasKey` eqTyConKey
_ -> False
+
isIPPred ty = case tyConAppTyCon_maybe ty of
- Just tyCon | Just _ <- tyConIP_maybe tyCon -> True
- _ -> False
+ Just tyCon -> tyConName tyCon == ipClassName
+ _ -> False
+
+isIPPred_maybe :: Type -> Maybe (FastString, Type)
+isIPPred_maybe ty =
+ do (tc,[t1,t2]) <- splitTyConApp_maybe ty
+ guard (tyConName tc == ipClassName)
+ x <- isStrLitTy t1
+ return (x,t2)
\end{code}
Make PredTypes
@@ -882,13 +887,6 @@ mkPrimEqPred ty1 ty2
k = typeKind ty1
\end{code}
---------------------- Implicit parameters ---------------------------------
-
-\begin{code}
-mkIPPred :: IPName Name -> Type -> PredType
-mkIPPred ip ty = TyConApp (ipTyCon ip) [ty]
-\end{code}
-
--------------------- Dictionary types ---------------------------------
\begin{code}
mkClassPred :: Class -> [Type] -> PredType
@@ -941,14 +939,12 @@ Decomposing PredType
\begin{code}
data PredTree = ClassPred Class [Type]
| EqPred Type Type
- | IPPred (IPName Name) Type
| TuplePred [PredType]
| IrredPred PredType
predTreePredType :: PredTree -> PredType
predTreePredType (ClassPred clas tys) = mkClassPred clas tys
predTreePredType (EqPred ty1 ty2) = mkEqPred ty1 ty2
-predTreePredType (IPPred ip ty) = mkIPPred ip ty
predTreePredType (TuplePred tys) = mkBoxedTupleTy tys
predTreePredType (IrredPred ty) = ty
@@ -959,9 +955,6 @@ classifyPredType ev_ty = case splitTyConApp_maybe ev_ty of
Just (tc, tys) | tc `hasKey` eqTyConKey
, let [_, ty1, ty2] = tys
-> EqPred ty1 ty2
- Just (tc, tys) | Just ip <- tyConIP_maybe tc
- , let [ty] = tys
- -> IPPred ip ty
Just (tc, tys) | isTupleTyCon tc
-> TuplePred tys
_ -> IrredPred ev_ty
@@ -990,11 +983,6 @@ getEqPredTys_maybe ty
= case splitTyConApp_maybe ty of
Just (tc, [_, ty1, ty2]) | tc `hasKey` eqTyConKey -> Just (ty1, ty2)
_ -> Nothing
-
-getIPPredTy_maybe :: PredType -> Maybe (IPName Name, Type)
-getIPPredTy_maybe ty = case splitTyConApp_maybe ty of
- Just (tc, [ty1]) | Just ip <- tyConIP_maybe tc -> Just (ip, ty1)
- _ -> Nothing
\end{code}
%************************************************************************
diff --git a/compiler/types/TypeRep.lhs b/compiler/types/TypeRep.lhs
index 3605851101..327ac78d71 100644
--- a/compiler/types/TypeRep.lhs
+++ b/compiler/types/TypeRep.lhs
@@ -551,17 +551,18 @@ instance Outputable Type where
instance Outputable TyLit where
ppr = pprTyLit
-instance Outputable name => OutputableBndr (IPName name) where
- pprBndr _ n = ppr n -- Simple for now
- pprInfixOcc n = ppr n
- pprPrefixOcc n = ppr n
-
------------------
-- OK, here's the main printer
ppr_type :: Prec -> Type -> SDoc
ppr_type _ (TyVarTy tv) = ppr_tvar tv
+
+ppr_type _ (TyConApp tc [LitTy (StrTyLit n),ty])
+ | tc `hasKey` ipClassNameKey
+ = char '?' <> ftext n <> ptext (sLit "::") <> ppr_type TopPrec ty
+
ppr_type p (TyConApp tc tys) = pprTcApp p ppr_type tc tys
+
ppr_type p (LitTy l) = ppr_tylit p l
ppr_type p ty@(ForAllTy {}) = ppr_forall_type p ty
@@ -661,7 +662,6 @@ pprTcApp _ _ tc [] -- No brackets for SymOcc
pprTcApp _ pp tc [ty]
| tc `hasKey` listTyConKey = pprPromotionQuote tc <> brackets (pp TopPrec ty)
| tc `hasKey` parrTyConKey = pprPromotionQuote tc <> paBrackets (pp TopPrec ty)
- | Just n <- tyConIP_maybe tc = ppr n <> ptext (sLit "::") <> pp TopPrec ty
pprTcApp p pp tc tys
| isTupleTyCon tc && tyConArity tc == length tys