diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2015-05-11 23:19:14 +0100 |
---|---|---|
committer | Simon Peyton Jones <simonpj@microsoft.com> | 2015-05-18 13:44:15 +0100 |
commit | ffc21506894c7887d3620423aaf86bc6113a1071 (patch) | |
tree | c36353b98b3e5eeb9a257b39d95e56f441aa36da /compiler/iface/TcIface.hs | |
parent | 76024fdbad0f6daedd8757b974eace3314bd4eec (diff) | |
download | haskell-ffc21506894c7887d3620423aaf86bc6113a1071.tar.gz |
Refactor tuple constraints
Make tuple constraints be handled by a perfectly ordinary
type class, with the component constraints being the
superclasses:
class (c1, c2) => (c2, c2)
This change was provoked by
#10359 inability to re-use a given tuple
constraint as a whole
#9858 confusion between term tuples
and constraint tuples
but it's generally a very nice simplification. We get rid of
- In Type, the TuplePred constructor of PredTree,
and all the code that dealt with TuplePreds
- In TcEvidence, the constructors EvTupleMk, EvTupleSel
See Note [How tuples work] in TysWiredIn.
Of course, nothing is ever entirely simple. This one
proved quite fiddly.
- I did quite a bit of renaming, which makes this patch
touch a lot of modules. In partiuclar tupleCon -> tupleDataCon.
- I made constraint tuples known-key rather than wired-in.
This is different to boxed/unboxed tuples, but it proved
awkward to have all the superclass selectors wired-in.
Easier just to use the standard mechanims.
- While I was fiddling with known-key names, I split the TH Name
definitions out of DsMeta into a new module THNames. That meant
that the known-key names can all be gathered in PrelInfo, without
causing module loops.
- I found that the parser was parsing an import item like
T( .. )
as a *data constructor* T, and then using setRdrNameSpace to
fix it. Stupid! So I changed the parser to parse a *type
constructor* T, which means less use of setRdrNameSpace.
I also improved setRdrNameSpace to behave better on Exact Names.
Largely on priciple; I don't think it matters a lot.
- When compiling a data type declaration for a wired-in thing like
tuples (,), or lists, we don't really need to look at the
declaration. We have the wired-in thing! And not doing so avoids
having to line up the uniques for data constructor workers etc.
See Note [Declarations for wired-in things]
- I found that FunDeps.oclose wasn't taking superclasses into
account; easily fixed.
- Some error message refactoring for invalid constraints in TcValidity
- Haddock needs to absorb the change too; so there is a submodule update
Diffstat (limited to 'compiler/iface/TcIface.hs')
-rw-r--r-- | compiler/iface/TcIface.hs | 84 |
1 files changed, 60 insertions, 24 deletions
diff --git a/compiler/iface/TcIface.hs b/compiler/iface/TcIface.hs index 1beae57cc7..2553643525 100644 --- a/compiler/iface/TcIface.hs +++ b/compiler/iface/TcIface.hs @@ -49,7 +49,7 @@ import DataCon import PrelNames import TysWiredIn import TysPrim ( superKindTyConName ) -import BasicTypes ( strongLoopBreaker ) +import BasicTypes ( strongLoopBreaker, Arity, TupleSort(..), Boxity(..) ) import Literal import qualified Var import VarEnv @@ -643,7 +643,7 @@ tcIfaceRule (IfaceRule {ifRuleName = name, ifActivation = act, ifRuleBndrs = bnd -- or, even if it is (module loop, perhaps) -- we'll just leave it in the non-local set where - -- This function *must* mirror exactly what Rules.topFreeName does + -- This function *must* mirror exactly what Rules.roughTopNames does -- We could have stored the ru_rough field in the iface file -- but that would be redundant, I think. -- The only wrinkle is that we must not be deceived by @@ -652,6 +652,7 @@ tcIfaceRule (IfaceRule {ifRuleName = name, ifActivation = act, ifRuleBndrs = bnd -- to write them out in coreRuleToIfaceRule ifTopFreeName :: IfaceExpr -> Maybe Name ifTopFreeName (IfaceType (IfaceTyConApp tc _ )) = Just (ifaceTyConName tc) + ifTopFreeName (IfaceType (IfaceTupleTy s _ ts)) = Just (tupleTyConName s (length (tcArgsIfaceTypes ts))) ifTopFreeName (IfaceApp f _) = ifTopFreeName f ifTopFreeName (IfaceExt n) = Just n ifTopFreeName _ = Nothing @@ -805,7 +806,7 @@ tcIfaceVectInfo mod typeEnv (IfaceVectInfo -- name is not a tycon => internal inconsistency Just _ -> notATyConErr -- tycon is external - Nothing -> tcIfaceTyCon (IfaceTc name) + Nothing -> tcIfaceTyConByName name } notATyConErr = pprPanic "TcIface.tcIfaceVectInfo: not a tycon" (ppr name) @@ -824,6 +825,7 @@ tcIfaceType (IfaceAppTy t1 t2) = do { t1' <- tcIfaceType t1; t2' <- tcIfaceT tcIfaceType (IfaceLitTy l) = do { l1 <- tcIfaceTyLit l; return (LitTy l1) } tcIfaceType (IfaceFunTy t1 t2) = tcIfaceTypeFun t1 t2 tcIfaceType (IfaceDFunTy t1 t2) = tcIfaceTypeFun t1 t2 +tcIfaceType (IfaceTupleTy s i tks) = tcIfaceTupleTy s i tks tcIfaceType (IfaceTyConApp tc tks) = do { tc' <- tcIfaceTyCon tc ; tks' <- tcIfaceTcArgs tks ; return (mkTyConApp tc' tks') } @@ -842,6 +844,34 @@ tcIfaceKind k = tcIfaceType k tcIfaceKindFun :: IfaceKind -> IfaceKind -> IfL Type tcIfaceKindFun t1 t2 = do { t1' <- tcIfaceKind t1; t2' <- tcIfaceKind t2; return (FunTy t1' t2') } +tcIfaceTupleTy :: TupleSort -> IfaceTyConInfo -> IfaceTcArgs -> IfL Type +tcIfaceTupleTy sort info args + = do { args' <- tcIfaceTcArgs args + ; let arity = length args' + ; base_tc <- tcTupleTyCon sort arity + ; case info of + NoIfaceTyConInfo + -> return (mkTyConApp base_tc args') + + IfacePromotedTyCon + | Just tc <- promotableTyCon_maybe base_tc + -> return (mkTyConApp tc args') + | otherwise + -> panic "tcIfaceTupleTy" (ppr base_tc) + + IfacePromotedDataCon + -> do { let tc = promoteDataCon (tyConSingleDataCon base_tc) + kind_args = map typeKind args' + ; return (mkTyConApp tc (kind_args ++ args')) } } + +tcTupleTyCon :: TupleSort -> Arity -> IfL TyCon +tcTupleTyCon sort arity + = case sort of + ConstraintTuple -> do { thing <- tcIfaceGlobal (cTupleTyConName arity) + ; return (tyThingTyCon thing) } + BoxedTuple -> return (tupleTyCon Boxed arity) + UnboxedTuple -> return (tupleTyCon Unboxed arity) + tcIfaceTcArgs :: IfaceTcArgs -> IfL [Type] tcIfaceTcArgs args = case args of @@ -942,15 +972,15 @@ tcIfaceExpr (IfaceFCall cc ty) = do dflags <- getDynFlags return (Var (mkFCallId dflags u cc ty')) -tcIfaceExpr (IfaceTuple boxity args) = do - args' <- mapM tcIfaceExpr args - -- Put the missing type arguments back in - let con_args = map (Type . exprType) args' ++ args' - return (mkApps (Var con_id) con_args) +tcIfaceExpr (IfaceTuple sort args) + = do { args' <- mapM tcIfaceExpr args + ; tc <- tcTupleTyCon sort arity + ; let con_args = map (Type . exprType) args' ++ args' + -- Put the missing type arguments back in + con_id = dataConWorkId (tyConSingleDataCon tc) + ; return (mkApps (Var con_id) con_args) } where arity = length args - con_id = dataConWorkId (tupleCon boxity arity) - tcIfaceExpr (IfaceLam (bndr, os) body) = bindIfaceBndr bndr $ \bndr' -> @@ -1059,7 +1089,7 @@ tcIfaceLit :: Literal -> IfL Literal -- so tcIfaceLit just fills in the type. -- See Note [Integer literals] in Literal tcIfaceLit (LitInteger i _) - = do t <- tcIfaceTyCon (IfaceTc integerTyConName) + = do t <- tcIfaceTyConByName integerTyConName return (mkLitInteger i (mkTyConTy t)) tcIfaceLit lit = return lit @@ -1237,6 +1267,7 @@ tcIfaceGlobal name -- sure the instances and RULES of this thing (particularly TyCon) are loaded -- Imagine: f :: Double -> Double = do { ifCheckWiredInThing thing; return thing } + | otherwise = do { env <- getGblEnv ; case if_rec_types env of { -- Note [Tying the knot] @@ -1279,20 +1310,25 @@ tcIfaceGlobal name -- Because if M.hs also has M.hs-boot, M.T will *already be* in the HPT, but in its -- emasculated form (e.g. lacking data constructors). +tcIfaceTyConByName :: IfExtName -> IfL TyCon +tcIfaceTyConByName name + = do { thing <- tcIfaceGlobal name + ; return (tyThingTyCon thing) } + tcIfaceTyCon :: IfaceTyCon -> IfL TyCon -tcIfaceTyCon itc - = do { - ; thing <- tcIfaceGlobal (ifaceTyConName itc) - ; case itc of - IfaceTc _ -> return $ tyThingTyCon thing - IfacePromotedDataCon _ -> return $ promoteDataCon $ tyThingDataCon thing - IfacePromotedTyCon name -> - let ktycon tc - | isSuperKind (tyConKind tc) = return tc - | Just prom_tc <- promotableTyCon_maybe tc = return prom_tc - | otherwise = pprPanic "tcIfaceTyCon" (ppr name $$ ppr thing) - in ktycon (tyThingTyCon thing) - } +tcIfaceTyCon (IfaceTyCon name info) + = do { thing <- tcIfaceGlobal name + ; case info of + NoIfaceTyConInfo -> return (tyThingTyCon thing) + IfacePromotedDataCon -> return (promoteDataCon (tyThingDataCon thing)) + -- Same Name as its underlying DataCon + IfacePromotedTyCon -> return (promote_tc (tyThingTyCon thing)) } + -- Same Name as its underlying TyCon + where + promote_tc tc + | Just prom_tc <- promotableTyCon_maybe tc = prom_tc + | isSuperKind (tyConKind tc) = tc + | otherwise = pprPanic "tcIfaceTyCon" (ppr name $$ ppr tc) tcIfaceCoAxiom :: Name -> IfL (CoAxiom Branched) tcIfaceCoAxiom name = do { thing <- tcIfaceGlobal name |