Commit 8366792e authored by eir@cis.upenn.edu's avatar eir@cis.upenn.edu

Implement overlapping type family instances.

An ordered, overlapping type family instance is introduced by 'type
instance
where', followed by equations. See the new section in the user manual
(7.7.2.2) for details. The canonical example is Boolean equality at the
type
level:

type family Equals (a :: k) (b :: k) :: Bool
type instance where
  Equals a a = True
  Equals a b = False

A branched family instance, such as this one, checks its equations in
order
and applies only the first the matches. As explained in the note
[Instance
checking within groups] in FamInstEnv.lhs, we must be careful not to
simplify,
say, (Equals Int b) to False, because b might later unify with Int.

This commit includes all of the commits on the overlapping-tyfams
branch. SPJ
requested that I combine all my commits over the past several months
into one
monolithic commit. The following GHC repos are affected: ghc, testsuite,
utils/haddock, libraries/template-haskell, and libraries/dph.

Here are some details for the interested:

- The definition of CoAxiom has been moved from TyCon.lhs to a
  new file CoAxiom.lhs. I made this decision because of the
  number of definitions necessary to support BranchList.

- BranchList is a GADT whose type tracks whether it is a
  singleton list or not-necessarily-a-singleton-list. The reason
  I introduced this type is to increase static checking of places
  where GHC code assumes that a FamInst or CoAxiom is indeed a
  singleton. This assumption takes place roughly 10 times
  throughout the code. I was worried that a future change to GHC
  would invalidate the assumption, and GHC might subtly fail to
  do the right thing. By explicitly labeling CoAxioms and
  FamInsts as being Unbranched (singleton) or
  Branched (not-necessarily-singleton), we make this assumption
  explicit and checkable. Furthermore, to enforce the accuracy of
  this label, the list of branches of a CoAxiom or FamInst is
  stored using a BranchList, whose constructors constrain its
  type index appropriately.

I think that the decision to use BranchList is probably the most
controversial decision I made from a code design point of view.
Although I provide conversions to/from ordinary lists, it is more
efficient to use the brList... functions provided in CoAxiom than
always to convert. The use of these functions does not wander far
from the core CoAxiom/FamInst logic.

BranchLists are motivated and explained in the note [Branched axioms] in
CoAxiom.lhs.

- The CoAxiom type has changed significantly. You can see the new
  type in CoAxiom.lhs. It uses a CoAxBranch type to track
  branches of the CoAxiom. Correspondingly various functions
  producing and consuming CoAxioms had to change, including the
  binary layout of interface files.

- To get branched axioms to work correctly, it is important to have a
  notion
  of type "apartness": two types are apart if they cannot unify, and no
  substitution of variables can ever get them to unify, even after type
family
  simplification. (This is different than the normal failure to unify
because
  of the type family bit.) This notion in encoded in tcApartTys, in
Unify.lhs.
  Because apartness is finer-grained than unification, the tcUnifyTys
now
  calls tcApartTys.

- CoreLinting axioms has been updated, both to reflect the new
  form of CoAxiom and to enforce the apartness rules of branch
  application. The formalization of the new rules is in
  docs/core-spec/core-spec.pdf.

- The FamInst type (in types/FamInstEnv.lhs) has changed
  significantly, paralleling the changes to CoAxiom. Of course,
  this forced minor changes in many files.

- There are several new Notes in FamInstEnv.lhs, including one
  discussing confluent overlap and why we're not doing it.

- lookupFamInstEnv, lookupFamInstEnvConflicts, and
  lookup_fam_inst_env' (the function that actually does the work)
  have all been more-or-less completely rewritten. There is a
  Note [lookup_fam_inst_env' implementation] describing the
  implementation. One of the changes that affects other files is
  to change the type of matches from a pair of (FamInst, [Type])
  to a new datatype (which now includes the index of the matching
  branch). This seemed a better design.

- The TySynInstD constructor in Template Haskell was updated to
  use the new datatype TySynEqn. I also bumped the TH version
  number, requiring changes to DPH cabal files. (That's why the
  DPH repo has an overlapping-tyfams branch.)

- As SPJ requested, I refactored some of the code in HsDecls:

 * splitting up TyDecl into SynDecl and DataDecl, correspondingly
   changing HsTyDefn to HsDataDefn (with only one constructor)

 * splitting FamInstD into TyFamInstD and DataFamInstD and
   splitting FamInstDecl into DataFamInstDecl and TyFamInstDecl

 * making the ClsInstD take a ClsInstDecl, for parallelism with
   InstDecl's other constructors

 * changing constructor TyFamily into FamDecl

 * creating a FamilyDecl type that stores the details for a family
   declaration; this is useful because FamilyDecls can appear in classes
but
   other decls cannot

 * restricting the associated types and associated type defaults for a
 * class
   to be the new, more restrictive types

 * splitting cid_fam_insts into cid_tyfam_insts and cid_datafam_insts,
   according to the new types

 * perhaps one or two more that I'm overlooking

None of these changes has far-reaching implications.

- The user manual, section 7.7.2.2, is updated to describe the new type
  family
  instances.
parent d3e2912a
......@@ -26,7 +26,8 @@ module MkId (
wrapNewTypeBody, unwrapNewTypeBody,
wrapFamInstBody, unwrapFamInstScrut,
wrapTypeFamInstBody, unwrapTypeFamInstScrut,
wrapTypeFamInstBody, wrapTypeUnbranchedFamInstBody, unwrapTypeFamInstScrut,
unwrapTypeUnbranchedFamInstScrut,
DataConBoxer(..), mkDataConRep, mkDataConWorkId,
......@@ -47,13 +48,15 @@ import TysPrim
import TysWiredIn
import PrelRules
import Type
import Coercion ( mkReflCo, mkAxInstCo, mkSymCo, coercionKind, mkUnsafeCo )
import Coercion ( mkReflCo, mkAxInstCo, mkSymCo, coercionKind, mkUnsafeCo,
mkUnbranchedAxInstCo )
import TcType
import MkCore
import CoreUtils ( exprType, mkCast )
import CoreUnfold
import Literal
import TyCon
import CoAxiom
import Class
import VarSet
import Name
......@@ -647,7 +650,7 @@ dataConArgUnpack arg_ty
unbox_tc_app tc tc_args con
| isNewTyCon tc
, let rep_ty = newTyConInstRhs tc tc_args
co = mkAxInstCo (newTyConCo tc) tc_args -- arg_ty ~ rep_ty
co = mkUnbranchedAxInstCo (newTyConCo tc) tc_args -- arg_ty ~ rep_ty
, (yes, rep_tys, unbox_rep, box_rep) <- dataConArgUnpack rep_ty
= ( yes, rep_tys
, \ arg_id ->
......@@ -661,7 +664,7 @@ dataConArgUnpack arg_ty
UnitBox -> do { rep_id <- newLocal (substTy subst rep_ty)
; return ([rep_id], Var rep_id) }
Boxer boxer -> boxer subst
; let sco = mkAxInstCo (newTyConCo tc) (substTys subst tc_args)
; let sco = mkUnbranchedAxInstCo (newTyConCo tc) (substTys subst tc_args)
; return (rep_ids, rep_expr `Cast` mkSymCo sco) } )
| otherwise
......@@ -769,7 +772,7 @@ wrapNewTypeBody tycon args result_expr
wrapFamInstBody tycon args $
mkCast result_expr (mkSymCo co)
where
co = mkAxInstCo (newTyConCo tycon) args
co = mkUnbranchedAxInstCo (newTyConCo tycon) args
-- When unwrapping, we do *not* apply any family coercion, because this will
-- be done via a CoPat by the type checker. We have to do it this way as
......@@ -779,7 +782,7 @@ wrapNewTypeBody tycon args result_expr
unwrapNewTypeBody :: TyCon -> [Type] -> CoreExpr -> CoreExpr
unwrapNewTypeBody tycon args result_expr
= ASSERT( isNewTyCon tycon )
mkCast result_expr (mkAxInstCo (newTyConCo tycon) args)
mkCast result_expr (mkUnbranchedAxInstCo (newTyConCo tycon) args)
-- If the type constructor is a representation type of a data instance, wrap
-- the expression into a cast adjusting the expression type, which is an
......@@ -789,26 +792,34 @@ unwrapNewTypeBody tycon args result_expr
wrapFamInstBody :: TyCon -> [Type] -> CoreExpr -> CoreExpr
wrapFamInstBody tycon args body
| Just co_con <- tyConFamilyCoercion_maybe tycon
= mkCast body (mkSymCo (mkAxInstCo co_con args))
= mkCast body (mkSymCo (mkUnbranchedAxInstCo co_con args))
| otherwise
= body
-- Same as `wrapFamInstBody`, but for type family instances, which are
-- represented by a `CoAxiom`, and not a `TyCon`
wrapTypeFamInstBody :: CoAxiom -> [Type] -> CoreExpr -> CoreExpr
wrapTypeFamInstBody axiom args body
= mkCast body (mkSymCo (mkAxInstCo axiom args))
wrapTypeFamInstBody :: CoAxiom br -> Int -> [Type] -> CoreExpr -> CoreExpr
wrapTypeFamInstBody axiom ind args body
= mkCast body (mkSymCo (mkAxInstCo axiom ind args))
wrapTypeUnbranchedFamInstBody :: CoAxiom Unbranched -> [Type] -> CoreExpr -> CoreExpr
wrapTypeUnbranchedFamInstBody axiom
= wrapTypeFamInstBody axiom 0
unwrapFamInstScrut :: TyCon -> [Type] -> CoreExpr -> CoreExpr
unwrapFamInstScrut tycon args scrut
| Just co_con <- tyConFamilyCoercion_maybe tycon
= mkCast scrut (mkAxInstCo co_con args)
= mkCast scrut (mkUnbranchedAxInstCo co_con args) -- data instances only
| otherwise
= scrut
unwrapTypeFamInstScrut :: CoAxiom -> [Type] -> CoreExpr -> CoreExpr
unwrapTypeFamInstScrut axiom args scrut
= mkCast scrut (mkAxInstCo axiom args)
unwrapTypeFamInstScrut :: CoAxiom br -> Int -> [Type] -> CoreExpr -> CoreExpr
unwrapTypeFamInstScrut axiom ind args scrut
= mkCast scrut (mkAxInstCo axiom ind args)
unwrapTypeUnbranchedFamInstScrut :: CoAxiom Unbranched -> [Type] -> CoreExpr -> CoreExpr
unwrapTypeUnbranchedFamInstScrut axiom
= unwrapTypeFamInstScrut axiom 0
\end{code}
......
......@@ -43,6 +43,7 @@ import Kind
import Type
import TypeRep
import TyCon
import CoAxiom
import BasicTypes
import StaticFlags
import ListSetOps
......@@ -50,6 +51,8 @@ import PrelNames
import Outputable
import FastString
import Util
import Unify
import InstEnv ( instanceBindFun )
import Control.Monad
import MonadUtils
import Data.Maybe
......@@ -410,6 +413,30 @@ kind coercions and produce the following substitution which is to be
applied in the type variables:
k_ag ~~> * -> *
Note [Conflict checking with AxiomInstCo]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider the following type family and axiom:
type family Equal (a :: k) (b :: k) :: Bool
type instance where
Equal a a = True
Equal a b = False
--
Equal :: forall k::BOX. k -> k -> Bool
axEqual :: { forall k::BOX. forall a::k. Equal k a a ~ True
; forall k::BOX. forall a::k. forall b::k. Equal k a b ~ False }
We wish to disallow (axEqual[1] <*> <Int> <Int). (Recall that the index is 0-based,
so this is the second branch of the axiom.) The problem is that, on the surface, it
seems that (axEqual[1] <*> <Int> <Int>) :: (Equal * Int Int ~ False) and that all is
OK. But, all is not OK: we want to use the first branch of the axiom in this case,
not the second. The problem is that the parameters of the first branch can unify with
the supplied coercions, thus meaning that the first branch should be taken. See also
Note [Instance checking within groups] in types/FamInstEnv.lhs.
However, if the right-hand side of the previous branch coincides with the right-hand
side of the selected branch, we wish to accept the AxiomInstCo. See also Note
[Confluence checking within groups], also in types/FamInstEnv.lhs.
%************************************************************************
%* *
......@@ -909,24 +936,40 @@ lintCoercion (InstCo co arg_ty)
-> failWithL (ptext (sLit "Kind mis-match in inst coercion"))
_ -> failWithL (ptext (sLit "Bad argument of inst")) }
lintCoercion co@(AxiomInstCo (CoAxiom { co_ax_tvs = ktvs
, co_ax_lhs = lhs
, co_ax_rhs = rhs })
cos)
= do { -- See Note [Kind instantiation in coercions]
unless (equalLength ktvs cos) (bad_ax (ptext (sLit "lengths")))
lintCoercion co@(AxiomInstCo con ind cos)
= do { unless (0 <= ind && ind < brListLength (coAxiomBranches con))
(bad_ax (ptext (sLit "index out of range")))
-- See Note [Kind instantiation in coercions]
; let CoAxBranch { cab_tvs = ktvs
, cab_lhs = lhs
, cab_rhs = rhs } = coAxiomNthBranch con ind
; unless (equalLength ktvs cos) (bad_ax (ptext (sLit "lengths")))
; in_scope <- getInScope
; let empty_subst = mkTvSubst in_scope emptyTvSubstEnv
; (subst_l, subst_r) <- foldlM check_ki
(empty_subst, empty_subst)
(ktvs `zip` cos)
; let lhs' = Type.substTy subst_l lhs
; let lhs' = Type.substTys subst_l lhs
rhs' = Type.substTy subst_r rhs
; return (typeKind lhs', lhs', rhs') }
; case check_no_conflict lhs' (ind - 1) of
Just bad_index -> bad_ax $ ptext (sLit "inconsistent with") <+> (ppr bad_index)
Nothing -> return ()
; return (typeKind rhs', mkTyConApp (coAxiomTyCon con) lhs', rhs') }
where
bad_ax what = addErrL (hang (ptext (sLit "Bad axiom application") <+> parens what)
2 (ppr co))
-- See Note [Conflict checking with AxiomInstCo]
check_no_conflict :: [Type] -> Int -> Maybe Int
check_no_conflict _ (-1) = Nothing
check_no_conflict lhs' j
| SurelyApart <- tcApartTys instanceBindFun lhs' lhsj
= check_no_conflict lhs' (j-1)
| otherwise
= Just j
where
(CoAxBranch { cab_lhs = lhsj }) = coAxiomNthBranch con j
check_ki (subst_l, subst_r) (ktv, co)
= do { (k, t1, t2) <- lintCoercion co
; let ktv_kind = Type.substTy subst_l (tyVarKind ktv)
......
......@@ -74,6 +74,7 @@ data Ty
| UnsafeCoercion Ty Ty
| InstCoercion Ty Ty
| NthCoercion Int Ty
| AxiomCoercion (Qual Tcon) Int [Ty]
| LRCoercion LeftOrRight Ty
data LeftOrRight = CLeft | CRight
......
......@@ -20,6 +20,7 @@ import Module
import CoreSyn
import HscTypes
import TyCon
import CoAxiom
-- import Class
import TypeRep
import Type
......@@ -112,7 +113,7 @@ collect_tdefs _ _ tdefs = tdefs
qtc :: DynFlags -> TyCon -> C.Qual C.Tcon
qtc dflags = make_con_qid dflags . tyConName
qcc :: DynFlags -> CoAxiom -> C.Qual C.Tcon
qcc :: DynFlags -> CoAxiom br -> C.Qual C.Tcon
qcc dflags = make_con_qid dflags . co_ax_name
make_cdef :: DynFlags -> DataCon -> C.Cdef
......@@ -322,7 +323,7 @@ make_co dflags (TyConAppCo tc cos) = make_conAppCo dflags (qtc dflags tc) cos
make_co dflags (AppCo c1 c2) = C.Tapp (make_co dflags c1) (make_co dflags c2)
make_co dflags (ForAllCo tv co) = C.Tforall (make_tbind tv) (make_co dflags co)
make_co _ (CoVarCo cv) = C.Tvar (make_var_id (coVarName cv))
make_co dflags (AxiomInstCo cc cos) = make_conAppCo dflags (qcc dflags cc) cos
make_co dflags (AxiomInstCo cc ind cos) = C.AxiomCoercion (qcc dflags cc) ind (map (make_co dflags) cos)
make_co dflags (UnsafeCo t1 t2) = C.UnsafeCoercion (make_ty dflags t1) (make_ty dflags t2)
make_co dflags (SymCo co) = C.SymCoercion (make_co dflags co)
make_co dflags (TransCo c1 c2) = C.TransCoercion (make_co dflags c1) (make_co dflags c2)
......
......@@ -465,7 +465,7 @@ data CoercionMap a
, km_app :: CoercionMap (CoercionMap a)
, km_forall :: CoercionMap (TypeMap a)
, km_var :: VarMap a
, km_axiom :: NameEnv (ListMap CoercionMap a)
, km_axiom :: NameEnv (IntMap.IntMap (ListMap CoercionMap a))
, km_unsafe :: TypeMap (TypeMap a)
, km_sym :: CoercionMap a
, km_trans :: CoercionMap (CoercionMap a)
......@@ -503,7 +503,7 @@ mapC f (KM { km_refl = krefl, km_tc_app = ktc
, km_app = mapTM (mapTM f) kapp
, km_forall = mapTM (mapTM f) kforall
, km_var = mapTM f kvar
, km_axiom = mapNameEnv (mapTM f) kax
, km_axiom = mapNameEnv (IntMap.map (mapTM f)) kax
, km_unsafe = mapTM (mapTM f) kunsafe
, km_sym = mapTM f ksym
, km_trans = mapTM (mapTM f) ktrans
......@@ -517,36 +517,36 @@ lkC env co m
| EmptyKM <- m = Nothing
| otherwise = go co m
where
go (Refl ty) = km_refl >.> lkT env ty
go (TyConAppCo tc cs) = km_tc_app >.> lkNamed tc >=> lkList (lkC env) cs
go (AxiomInstCo ax cs) = km_axiom >.> lkNamed ax >=> lkList (lkC env) cs
go (AppCo c1 c2) = km_app >.> lkC env c1 >=> lkC env c2
go (TransCo c1 c2) = km_trans >.> lkC env c1 >=> lkC env c2
go (UnsafeCo t1 t2) = km_unsafe >.> lkT env t1 >=> lkT env t2
go (InstCo c t) = km_inst >.> lkC env c >=> lkT env t
go (ForAllCo v c) = km_forall >.> lkC (extendCME env v) c >=> lkBndr env v
go (CoVarCo v) = km_var >.> lkVar env v
go (SymCo c) = km_sym >.> lkC env c
go (NthCo n c) = km_nth >.> lookupTM n >=> lkC env c
go (LRCo CLeft c) = km_left >.> lkC env c
go (LRCo CRight c) = km_right >.> lkC env c
go (Refl ty) = km_refl >.> lkT env ty
go (TyConAppCo tc cs) = km_tc_app >.> lkNamed tc >=> lkList (lkC env) cs
go (AxiomInstCo ax ind cs) = km_axiom >.> lkNamed ax >=> lookupTM ind >=> lkList (lkC env) cs
go (AppCo c1 c2) = km_app >.> lkC env c1 >=> lkC env c2
go (TransCo c1 c2) = km_trans >.> lkC env c1 >=> lkC env c2
go (UnsafeCo t1 t2) = km_unsafe >.> lkT env t1 >=> lkT env t2
go (InstCo c t) = km_inst >.> lkC env c >=> lkT env t
go (ForAllCo v c) = km_forall >.> lkC (extendCME env v) c >=> lkBndr env v
go (CoVarCo v) = km_var >.> lkVar env v
go (SymCo c) = km_sym >.> lkC env c
go (NthCo n c) = km_nth >.> lookupTM n >=> lkC env c
go (LRCo CLeft c) = km_left >.> lkC env c
go (LRCo CRight c) = km_right >.> lkC env c
xtC :: CmEnv -> Coercion -> XT a -> CoercionMap a -> CoercionMap a
xtC env co f EmptyKM = xtC env co f wrapEmptyKM
xtC env (Refl ty) f m = m { km_refl = km_refl m |> xtT env ty f }
xtC env (TyConAppCo tc cs) f m = m { km_tc_app = km_tc_app m |> xtNamed tc |>> xtList (xtC env) cs f }
xtC env (AxiomInstCo ax cs) f m = m { km_axiom = km_axiom m |> xtNamed ax |>> xtList (xtC env) cs f }
xtC env (AppCo c1 c2) f m = m { km_app = km_app m |> xtC env c1 |>> xtC env c2 f }
xtC env (TransCo c1 c2) f m = m { km_trans = km_trans m |> xtC env c1 |>> xtC env c2 f }
xtC env (UnsafeCo t1 t2) f m = m { km_unsafe = km_unsafe m |> xtT env t1 |>> xtT env t2 f }
xtC env (InstCo c t) f m = m { km_inst = km_inst m |> xtC env c |>> xtT env t f }
xtC env (ForAllCo v c) f m = m { km_forall = km_forall m |> xtC (extendCME env v) c
|>> xtBndr env v f }
xtC env (CoVarCo v) f m = m { km_var = km_var m |> xtVar env v f }
xtC env (SymCo c) f m = m { km_sym = km_sym m |> xtC env c f }
xtC env (NthCo n c) f m = m { km_nth = km_nth m |> xtInt n |>> xtC env c f }
xtC env (LRCo CLeft c) f m = m { km_left = km_left m |> xtC env c f }
xtC env (LRCo CRight c) f m = m { km_right = km_right m |> xtC env c f }
xtC env (Refl ty) f m = m { km_refl = km_refl m |> xtT env ty f }
xtC env (TyConAppCo tc cs) f m = m { km_tc_app = km_tc_app m |> xtNamed tc |>> xtList (xtC env) cs f }
xtC env (AxiomInstCo ax ind cs) f m = m { km_axiom = km_axiom m |> xtNamed ax |>> xtInt ind |>> xtList (xtC env) cs f }
xtC env (AppCo c1 c2) f m = m { km_app = km_app m |> xtC env c1 |>> xtC env c2 f }
xtC env (TransCo c1 c2) f m = m { km_trans = km_trans m |> xtC env c1 |>> xtC env c2 f }
xtC env (UnsafeCo t1 t2) f m = m { km_unsafe = km_unsafe m |> xtT env t1 |>> xtT env t2 f }
xtC env (InstCo c t) f m = m { km_inst = km_inst m |> xtC env c |>> xtT env t f }
xtC env (ForAllCo v c) f m = m { km_forall = km_forall m |> xtC (extendCME env v) c
|>> xtBndr env v f }
xtC env (CoVarCo v) f m = m { km_var = km_var m |> xtVar env v f }
xtC env (SymCo c) f m = m { km_sym = km_sym m |> xtC env c f }
xtC env (NthCo n c) f m = m { km_nth = km_nth m |> xtInt n |>> xtC env c f }
xtC env (LRCo CLeft c) f m = m { km_left = km_left m |> xtC env c f }
xtC env (LRCo CRight c) f m = m { km_right = km_right m |> xtC env c f }
fdC :: (a -> b -> b) -> CoercionMap a -> b -> b
fdC _ EmptyKM = \z -> z
......@@ -555,7 +555,7 @@ fdC k m = foldTM k (km_refl m)
. foldTM (foldTM k) (km_app m)
. foldTM (foldTM k) (km_forall m)
. foldTM k (km_var m)
. foldTM (foldTM k) (km_axiom m)
. foldTM (foldTM (foldTM k)) (km_axiom m)
. foldTM (foldTM k) (km_unsafe m)
. foldTM k (km_sym m)
. foldTM (foldTM k) (km_trans m)
......
......@@ -830,7 +830,8 @@ ds_tc_coercion subst tc_co
go (TcForAllCo tv co) = mkForAllCo tv' (ds_tc_coercion subst' co)
where
(subst', tv') = Coercion.substTyVarBndr subst tv
go (TcAxiomInstCo ax tys) = mkAxInstCo ax (map (Coercion.substTy subst) tys)
go (TcAxiomInstCo ax ind tys)
= mkAxInstCo ax ind (map (Coercion.substTy subst) tys)
go (TcSymCo co) = mkSymCo (go co)
go (TcTransCo co1 co2) = mkTransCo (go co1) (go co2)
go (TcNthCo n co) = mkNthCo n (go co)
......
This diff is collapsed.
......@@ -384,6 +384,7 @@ Library
FunDeps
InstEnv
TyCon
CoAxiom
Kind
Type
TypeRep
......
......@@ -156,36 +156,39 @@ cvtDec (PragmaD prag)
cvtDec (TySynD tc tvs rhs)
= do { (_, tc', tvs') <- cvt_tycl_hdr [] tc tvs
; rhs' <- cvtType rhs
; returnL $ TyClD (TyDecl { tcdLName = tc'
; returnL $ TyClD (SynDecl { tcdLName = tc'
, tcdTyVars = tvs', tcdFVs = placeHolderNames
, tcdTyDefn = TySynonym rhs' }) }
, tcdRhs = rhs' }) }
cvtDec (DataD ctxt tc tvs constrs derivs)
= do { (ctxt', tc', tvs') <- cvt_tycl_hdr ctxt tc tvs
; cons' <- mapM cvtConstr constrs
; derivs' <- cvtDerivs derivs
; let defn = TyData { td_ND = DataType, td_cType = Nothing
, td_ctxt = ctxt'
, td_kindSig = Nothing
, td_cons = cons', td_derivs = derivs' }
; returnL $ TyClD (TyDecl { tcdLName = tc', tcdTyVars = tvs'
, tcdTyDefn = defn, tcdFVs = placeHolderNames }) }
; let defn = HsDataDefn { dd_ND = DataType, dd_cType = Nothing
, dd_ctxt = ctxt'
, dd_kindSig = Nothing
, dd_cons = cons', dd_derivs = derivs' }
; returnL $ TyClD (DataDecl { tcdLName = tc', tcdTyVars = tvs'
, tcdDataDefn = defn, tcdFVs = placeHolderNames }) }
cvtDec (NewtypeD ctxt tc tvs constr derivs)
= do { (ctxt', tc', tvs') <- cvt_tycl_hdr ctxt tc tvs
; con' <- cvtConstr constr
; derivs' <- cvtDerivs derivs
; let defn = TyData { td_ND = NewType, td_cType = Nothing
, td_ctxt = ctxt'
, td_kindSig = Nothing
, td_cons = [con'], td_derivs = derivs' }
; returnL $ TyClD (TyDecl { tcdLName = tc', tcdTyVars = tvs'
, tcdTyDefn = defn, tcdFVs = placeHolderNames }) }
; let defn = HsDataDefn { dd_ND = NewType, dd_cType = Nothing
, dd_ctxt = ctxt'
, dd_kindSig = Nothing
, dd_cons = [con'], dd_derivs = derivs' }
; returnL $ TyClD (DataDecl { tcdLName = tc', tcdTyVars = tvs'
, tcdDataDefn = defn, tcdFVs = placeHolderNames }) }
cvtDec (ClassD ctxt cl tvs fds decs)
= do { (cxt', tc', tvs') <- cvt_tycl_hdr ctxt cl tvs
; fds' <- mapM cvt_fundep fds
; (binds', sigs', fams', ats') <- cvt_ci_decs (ptext (sLit "a class declaration")) decs
; (binds', sigs', fams', ats', adts') <- cvt_ci_decs (ptext (sLit "a class declaration")) decs
; unless (null adts')
(failWith $ (ptext (sLit "Default data instance declarations are not allowed:"))
$$ (Outputable.ppr adts'))
; returnL $ TyClD $
ClassDecl { tcdCtxt = cxt', tcdLName = tc', tcdTyVars = tvs'
, tcdFDs = fds', tcdSigs = sigs', tcdMeths = binds'
......@@ -196,12 +199,12 @@ cvtDec (ClassD ctxt cl tvs fds decs)
cvtDec (InstanceD ctxt ty decs)
= do { let doc = ptext (sLit "an instance declaration")
; (binds', sigs', fams', ats') <- cvt_ci_decs doc decs
; (binds', sigs', fams', ats', adts') <- cvt_ci_decs doc decs
; unless (null fams') (failWith (mkBadDecMsg doc fams'))
; ctxt' <- cvtContext ctxt
; L loc ty' <- cvtType ty
; let inst_ty' = L loc $ mkImplicitHsForAllTy ctxt' $ L loc ty'
; returnL $ InstD (ClsInstD inst_ty' binds' sigs' ats') }
; returnL $ InstD (ClsInstD (ClsInstDecl inst_ty' binds' sigs' ats' adts')) }
cvtDec (ForeignD ford)
= do { ford' <- cvtForD ford
......@@ -210,7 +213,7 @@ cvtDec (ForeignD ford)
cvtDec (FamilyD flav tc tvs kind)
= do { (_, tc', tvs') <- cvt_tycl_hdr [] tc tvs
; kind' <- cvtMaybeKind kind
; returnL $ TyClD (TyFamily (cvtFamFlavour flav) tc' tvs' kind') }
; returnL $ TyClD (FamDecl (FamilyDecl (cvtFamFlavour flav) tc' tvs' kind')) }
where
cvtFamFlavour TypeFam = TypeFamily
cvtFamFlavour DataFam = DataFamily
......@@ -219,50 +222,61 @@ cvtDec (DataInstD ctxt tc tys constrs derivs)
= do { (ctxt', tc', typats') <- cvt_tyinst_hdr ctxt tc tys
; cons' <- mapM cvtConstr constrs
; derivs' <- cvtDerivs derivs
; let defn = TyData { td_ND = DataType, td_cType = Nothing
, td_ctxt = ctxt'
, td_kindSig = Nothing
, td_cons = cons', td_derivs = derivs' }
; let defn = HsDataDefn { dd_ND = DataType, dd_cType = Nothing
, dd_ctxt = ctxt'
, dd_kindSig = Nothing
, dd_cons = cons', dd_derivs = derivs' }
; returnL $ InstD $ FamInstD
{ lid_inst = FamInstDecl { fid_tycon = tc', fid_pats = typats'
, fid_defn = defn, fid_fvs = placeHolderNames } }}
; returnL $ InstD $ DataFamInstD
{ dfid_inst = DataFamInstDecl { dfid_tycon = tc', dfid_pats = typats'
, dfid_defn = defn, dfid_fvs = placeHolderNames } }}
cvtDec (NewtypeInstD ctxt tc tys constr derivs)
= do { (ctxt', tc', typats') <- cvt_tyinst_hdr ctxt tc tys
; con' <- cvtConstr constr
; derivs' <- cvtDerivs derivs
; let defn = TyData { td_ND = NewType, td_cType = Nothing
, td_ctxt = ctxt'
, td_kindSig = Nothing
, td_cons = [con'], td_derivs = derivs' }
; returnL $ InstD $ FamInstD
{ lid_inst = FamInstDecl { fid_tycon = tc', fid_pats = typats'
, fid_defn = defn, fid_fvs = placeHolderNames } } }
cvtDec (TySynInstD tc tys rhs)
= do { (_, tc', tys') <- cvt_tyinst_hdr [] tc tys
; let defn = HsDataDefn { dd_ND = NewType, dd_cType = Nothing
, dd_ctxt = ctxt'
, dd_kindSig = Nothing
, dd_cons = [con'], dd_derivs = derivs' }
; returnL $ InstD $ DataFamInstD
{ dfid_inst = DataFamInstDecl { dfid_tycon = tc', dfid_pats = typats'
, dfid_defn = defn, dfid_fvs = placeHolderNames } }}
cvtDec (TySynInstD tc eqns)
= do { tc' <- tconNameL tc
; eqns' <- mapM (cvtTySynEqn tc') eqns
; returnL $ InstD $ TyFamInstD
{ tfid_inst = TyFamInstDecl { tfid_eqns = eqns'
, tfid_group = (length eqns' /= 1)
, tfid_fvs = placeHolderNames } } }
----------------
cvtTySynEqn :: Located RdrName -> TySynEqn -> CvtM (LTyFamInstEqn RdrName)
cvtTySynEqn tc (TySynEqn lhs rhs)
= do { lhs' <- mapM cvtType lhs
; rhs' <- cvtType rhs
; returnL $ InstD $ FamInstD
{ lid_inst = FamInstDecl { fid_tycon = tc', fid_pats = tys'
, fid_defn = TySynonym rhs', fid_fvs = placeHolderNames } } }
; returnL $ TyFamInstEqn { tfie_tycon = tc
, tfie_pats = mkHsWithBndrs lhs'
, tfie_rhs = rhs' } }
----------------
cvt_ci_decs :: MsgDoc -> [TH.Dec]
-> CvtM (LHsBinds RdrName,
[LSig RdrName],
[LTyClDecl RdrName], -- Family decls
[LFamInstDecl RdrName])
[LFamilyDecl RdrName],
[LTyFamInstDecl RdrName],
[LDataFamInstDecl RdrName])
-- Convert the declarations inside a class or instance decl
-- ie signatures, bindings, and associated types
cvt_ci_decs doc decs
= do { decs' <- mapM cvtDec decs
; let (ats', bind_sig_decs') = partitionWith is_fam_inst decs'
; let (sigs', prob_binds') = partitionWith is_sig bind_sig_decs'
; let (ats', bind_sig_decs') = partitionWith is_tyfam_inst decs'
; let (adts', no_ats') = partitionWith is_datafam_inst bind_sig_decs'
; let (sigs', prob_binds') = partitionWith is_sig no_ats'
; let (binds', prob_fams') = partitionWith is_bind prob_binds'
; let (fams', bads) = partitionWith is_fam_decl prob_fams'
; unless (null bads) (failWith (mkBadDecMsg doc bads))
; return (listToBag binds', sigs', fams', ats') }
; return (listToBag binds', sigs', fams', ats', adts') }
----------------
cvt_tycl_hdr :: TH.Cxt -> TH.Name -> [TH.TyVarBndr]
......@@ -290,13 +304,17 @@ cvt_tyinst_hdr cxt tc tys
-- Partitioning declarations
-------------------------------------------------------------------
is_fam_decl :: LHsDecl RdrName -> Either (LTyClDecl RdrName) (LHsDecl RdrName)
is_fam_decl (L loc (TyClD d@(TyFamily {}))) = Left (L loc d)
is_fam_decl :: LHsDecl RdrName -> Either (LFamilyDecl RdrName) (LHsDecl RdrName)
is_fam_decl (L loc (TyClD (FamDecl { tcdFam = d }))) = Left (L loc d)
is_fam_decl decl = Right decl
is_fam_inst :: LHsDecl RdrName -> Either (LFamInstDecl RdrName) (LHsDecl RdrName)
is_fam_inst (L loc (Hs.InstD (FamInstD { lid_inst = d }))) = Left (L loc d)
is_fam_inst decl = Right decl
is_tyfam_inst :: LHsDecl RdrName -> Either (LTyFamInstDecl RdrName) (LHsDecl RdrName)
is_tyfam_inst (L loc (Hs.InstD (TyFamInstD { tfid_inst = d }))) = Left (L loc d)
is_tyfam_inst decl = Right decl
is_datafam_inst :: LHsDecl RdrName -> Either (LDataFamInstDecl RdrName) (LHsDecl RdrName)
is_datafam_inst (L loc (Hs.InstD (DataFamInstD { dfid_inst = d }))) = Left (L loc d)
is_datafam_inst decl = Right decl
is_sig :: LHsDecl RdrName -> Either (LSig RdrName) (LHsDecl RdrName)
is_sig (L loc (Hs.SigD sig)) = Left (L loc sig)
......
This diff is collapsed.
......@@ -68,7 +68,7 @@ module HsUtils(
collectLStmtBinders, collectStmtBinders,
hsLTyClDeclBinders, hsTyClDeclBinders, hsTyClDeclsBinders,
hsForeignDeclsBinders, hsGroupBinders, hsFamInstBinders,
hsForeignDeclsBinders, hsGroupBinders, hsDataFamInstBinders,
-- Collecting implicit binders
lStmtsImplicits, hsValBindsImplicits, lPatImplicits
......@@ -639,32 +639,35 @@ hsLTyClDeclBinders (L _ d) = hsTyClDeclBinders d
-------------------
hsTyClDeclBinders :: Eq name => TyClDecl name -> [Located name]
hsTyClDeclBinders (TyFamily {tcdLName = name}) = [name]
hsTyClDeclBinders (FamDecl { tcdFam = FamilyDecl { fdLName = name} }) = [name]
hsTyClDeclBinders (ForeignType {tcdLName = name}) = [name]
hsTyClDeclBinders (SynDecl {tcdLName = name}) = [name]
hsTyClDeclBinders (ClassDecl { tcdLName = cls_name, tcdSigs = sigs
, tcdATs = ats, tcdATDefs = fam_insts })
, tcdATs = ats })
= cls_name :
concatMap hsLTyClDeclBinders ats ++
concatMap (hsFamInstBinders . unLoc) fam_insts ++
map (fdLName . unLoc) ats ++
[n | L _ (TypeSig ns _) <- sigs, n <- ns]
hsTyClDeclBinders (TyDecl { tcdLName = name, tcdTyDefn = defn })
= name : hsTyDefnBinders defn
hsTyClDeclBinders (DataDecl { tcdLName = name, tcdDataDefn = defn })
= name : hsDataDefnBinders defn
-------------------
hsInstDeclBinders :: Eq name => InstDecl name -> [Located name]
hsInstDeclBinders (ClsInstD { cid_fam_insts = fis }) = concatMap (hsFamInstBinders . unLoc) fis
hsInstDeclBinders (FamInstD { lid_inst = fi }) = hsFamInstBinders fi
hsInstDeclBinders (ClsInstD { cid_inst = ClsInstDecl { cid_datafam_insts = dfis } })
= concatMap (hsDataFamInstBinders . unLoc) dfis
hsInstDeclBinders (DataFamInstD { dfid_inst = fi }) = hsDataFamInstBinders fi
hsInstDeclBinders (TyFamInstD {}) = []
-------------------
hsFamInstBinders :: Eq name => FamInstDecl name -> [Located name]
hsFamInstBinders (FamInstDecl { fid_defn = defn }) = hsTyDefnBinders defn
hsDataFamInstBinders :: Eq name => DataFamInstDecl name -> [Located name]
hsDataFamInstBinders (DataFamInstDecl { dfid_defn = defn })
= hsDataDefnBinders defn
-- There can't be repeated symbols because only data instances have binders
-------------------
hsTyDefnBinders :: Eq name => HsTyDefn name -> [Located name]
hsTyDefnBinders (TySynonym {}) = []
hsTyDefnBinders (TyData { td_cons = cons }) = hsConDeclsBinders cons
hsDataDefnBinders :: Eq name => HsDataDefn name -> [Located name]
hsDataDefnBinders (HsDataDefn { dd_cons = cons }) = hsConDeclsBinders cons
-- See Note [Binders in family instances]
-------------------
......
......@@ -1049,7 +1049,7 @@ instance Binary LeftOrRight where
_ -> return CRight }
instance Binary IfaceCoCon where
put_ bh (IfaceCoAx n) = do { putByte bh 0; put_ bh n }
put_ bh (IfaceCoAx n ind) = do { putByte bh 0; put_ bh n; put_ bh ind }
put_ bh IfaceReflCo = putByte bh 1
put_ bh IfaceUnsafeCo = putByte bh 2
put_ bh IfaceSymCo = putByte bh 3
......@@ -1061,7 +1061,7 @@ instance Binary IfaceCoCon where
get bh = do
h <- getByte bh
case h of
0 -> do { n <- get bh; return (IfaceCoAx n) }
0 -> do { n <- get bh; ind <- get bh; return (IfaceCoAx n ind) }
1 -> return IfaceReflCo
2 -> return IfaceUnsafeCo
3 -> return IfaceSymCo
......@@ -1356,12 +1356,11 @@ instance Binary IfaceDecl where
put_ bh a6
put_ bh a7
put_ bh (IfaceAxiom a1 a2 a3 a4) = do
put_ bh (IfaceAxiom a1 a2 a3) = do
putByte bh 5
put_ bh (occNameFS a1)
put_ bh a2
put_ bh a3
put_ bh a4
get bh = do
h <- getByte bh
......@@ -1401,9 +1400,19 @@ instance Binary IfaceDecl where
_ -> do a1 <- get bh
a2 <- get bh
a3 <- get bh
a4 <- get bh
occ <- return $! mkOccNameFS tcName a1
return (IfaceAxiom occ a2 a3 a4)
return (IfaceAxiom occ a2 a3)
instance Binary IfaceAxBranch where
put_ bh (IfaceAxBranch a1 a2 a3) = do
put_ bh a1
put_ bh a2
put_ bh a3
get bh = do
a1 <- get bh
a2 <- get bh
a3 <- get bh
return (IfaceAxBranch a1 a2 a3)
instance Binary ty => Binary (SynTyConRhs ty) where
put_ bh (SynFamilyTyCon a b) = putByte bh 0 >> put_ bh a >> put_ bh b
......@@ -1433,17 +1442,19 @@ instance Binary IfaceClsInst where
return (IfaceClsInst cls tys dfun flag orph)
instance Binary IfaceFamInst where
put_ bh (IfaceFamInst fam tys name orph) = do
put_ bh (IfaceFamInst fam group tys name orph) = do
put_ bh fam
put_ bh group
put_ bh tys
put_ bh name
put_ bh orph
get bh = do
fam <- get bh
group <- get bh
tys <- get bh
name <- get bh
orph <- get bh
return (IfaceFamInst fam tys name orph)
return (IfaceFamInst fam group tys name orph)
instance Binary OverlapFlag where
put_ bh (NoOverlap b) = putByte bh 0 >> put_ bh b
......
......@@ -20,7 +20,7 @@ module IfaceSyn (
IfaceBinding(..), IfaceConAlt(..),
IfaceIdInfo(..), IfaceIdDetails(..), IfaceUnfolding(..),
IfaceInfoItem(..), IfaceRule(..), IfaceAnnotation(..), IfaceAnnTarget,
IfaceClsInst(..), IfaceFamInst(..), IfaceTickish(..),
IfaceClsInst(..), IfaceFamInst(..), IfaceTickish(..), IfaceAxBranch(..),
-- Misc
ifaceDeclImplicitBndrs, visibleIfConDecls,
......@@ -102,10 +102,10 @@ data IfaceDecl
-- with the class recursive?
}
| IfaceAxiom { ifName :: OccName -- Axiom name
, ifTyVars :: [IfaceTvBndr] -- Axiom tyvars
, ifLHS :: IfaceType -- Axiom LHS
, ifRHS :: IfaceType } -- and RHS
| IfaceAxiom { ifName :: OccName, -- Axiom name
ifTyCon :: IfaceTyCon, -- LHS TyCon
ifAxBranches :: [IfaceAxBranch] -- Branches
}
| IfaceForeign { ifName :: OccName, -- Needs expanding when we move
-- beyond .NET
......@@ -126,6 +126,11 @@ data IfaceATDefault = IfaceATD [IfaceTvBndr] [IfaceType] IfaceType
-- 3. The instantiated family arguments
-- 2. The RHS of the synonym
-- this is just like CoAxBranch
data IfaceAxBranch = IfaceAxBranch { ifaxbTyVars :: [IfaceTvBndr]
, ifaxbLHS :: [IfaceType]
, ifaxbRHS :: IfaceType }
data IfaceConDecls
= IfAbstractTyCon Bool -- c.f TyCon.AbstractTyCon
| IfDataFamTyCon -- Data family
......@@ -165,11 +170,15 @@ data IfaceClsInst
-- If this instance decl is *used*, we'll record a usage on the dfun;
-- and if the head does not change it won't be used if it wasn't before
-- The ifFamInstTys field of IfaceFamInst contains a list of the rough
-- match types, one per branch... but each "rough match types" is itself
-- a list of Maybe IfaceTyCon. So, we get [[Maybe IfaceTyCon]].
data IfaceFamInst
= IfaceFamInst { ifFamInstFam :: IfExtName -- Family name