summaryrefslogtreecommitdiff
path: root/compiler/ghci
diff options
context:
space:
mode:
authorRichard Eisenberg <rae@cs.brynmawr.edu>2016-12-14 21:37:43 -0500
committerRichard Eisenberg <rae@cs.brynmawr.edu>2017-01-19 10:31:52 -0500
commite7985ed23ddc68b6a2e4af753578dc1d9e8ab4c9 (patch)
treeba8c4016e218710f8165db92d4b4c10e5559245a /compiler/ghci
parent38374caa9d6e1373d1b9d335d0f99f3664931fd9 (diff)
downloadhaskell-e7985ed23ddc68b6a2e4af753578dc1d9e8ab4c9.tar.gz
Update levity polymorphism
This commit implements the proposal in https://github.com/ghc-proposals/ghc-proposals/pull/29 and https://github.com/ghc-proposals/ghc-proposals/pull/35. Here are some of the pieces of that proposal: * Some of RuntimeRep's constructors have been shortened. * TupleRep and SumRep are now parameterized over a list of RuntimeReps. * This means that two types with the same kind surely have the same representation. Previously, all unboxed tuples had the same kind, and thus the fact above was false. * RepType.typePrimRep and friends now return a *list* of PrimReps. These functions can now work successfully on unboxed tuples. This change is necessary because we allow abstraction over unboxed tuple types and so cannot always handle unboxed tuples specially as we did before. * We sometimes have to create an Id from a PrimRep. I thus split PtrRep * into LiftedRep and UnliftedRep, so that the created Ids have the right strictness. * The RepType.RepType type was removed, as it didn't seem to help with * much. * The RepType.repType function is also removed, in favor of typePrimRep. * I have waffled a good deal on whether or not to keep VoidRep in TyCon.PrimRep. In the end, I decided to keep it there. PrimRep is *not* represented in RuntimeRep, and typePrimRep will never return a list including VoidRep. But it's handy to have in, e.g., ByteCodeGen and friends. I can imagine another design choice where we have a PrimRepV type that is PrimRep with an extra constructor. That seemed to be a heavier design, though, and I'm not sure what the benefit would be. * The last, unused vestiges of # (unliftedTypeKind) have been removed. * There were several pretty-printing bugs that this change exposed; * these are fixed. * We previously checked for levity polymorphism in the types of binders. * But we also must exclude levity polymorphism in function arguments. This is hard to check for, requiring a good deal of care in the desugarer. See Note [Levity polymorphism checking] in DsMonad. * In order to efficiently check for levity polymorphism in functions, it * was necessary to add a new bit of IdInfo. See Note [Levity info] in IdInfo. * It is now safe for unlifted types to be unsaturated in Core. Core Lint * is updated accordingly. * We can only know strictness after zonking, so several checks around * strictness in the type-checker (checkStrictBinds, the check for unlifted variables under a ~ pattern) have been moved to the desugarer. * Along the way, I improved the treatment of unlifted vs. banged * bindings. See Note [Strict binds checks] in DsBinds and #13075. * Now that we print type-checked source, we must be careful to print * ConLikes correctly. This is facilitated by a new HsConLikeOut constructor to HsExpr. Particularly troublesome are unlifted pattern synonyms that get an extra void# argument. * Includes a submodule update for haddock, getting rid of #. * New testcases: typecheck/should_fail/StrictBinds typecheck/should_fail/T12973 typecheck/should_run/StrictPats typecheck/should_run/T12809 typecheck/should_fail/T13105 patsyn/should_fail/UnliftedPSBind typecheck/should_fail/LevPolyBounded typecheck/should_compile/T12987 typecheck/should_compile/T11736 * Fixed tickets: #12809 #12973 #11736 #13075 #12987 * This also adds a test case for #13105. This test case is * "compile_fail" and succeeds, because I want the testsuite to monitor the error message. When #13105 is fixed, the test case will compile cleanly.
Diffstat (limited to 'compiler/ghci')
-rw-r--r--compiler/ghci/ByteCodeGen.hs64
-rw-r--r--compiler/ghci/ByteCodeItbls.hs6
-rw-r--r--compiler/ghci/Debugger.hs3
-rw-r--r--compiler/ghci/GHCi.hsc4
-rw-r--r--compiler/ghci/RtClosureInspect.hs49
5 files changed, 58 insertions, 68 deletions
diff --git a/compiler/ghci/ByteCodeGen.hs b/compiler/ghci/ByteCodeGen.hs
index 9a5e4141f1..a4373b459f 100644
--- a/compiler/ghci/ByteCodeGen.hs
+++ b/compiler/ghci/ByteCodeGen.hs
@@ -321,7 +321,7 @@ collect (_, e) = go [] e
where
go xs e | Just e' <- bcView e = go xs e'
go xs (AnnLam x (_,e))
- | repTypeArgs (idType x) `lengthExceeds` 1
+ | typePrimRep (idType x) `lengthExceeds` 1
= multiValException
| otherwise
= go (x:xs) e
@@ -551,8 +551,6 @@ schemeE d s p (AnnCase (_,scrut) _ _ []) = schemeE d s p scrut
schemeE d s p (AnnCase scrut bndr _ [(DataAlt dc, [bind1, bind2], rhs)])
| isUnboxedTupleCon dc -- handles pairs with one void argument (e.g. state token)
- , [rep_ty1] <- repTypeArgs (idType bind1)
- , [rep_ty2] <- repTypeArgs (idType bind2)
-- Convert
-- case .... of x { (# V'd-thing, a #) -> ... }
-- to
@@ -561,23 +559,25 @@ schemeE d s p (AnnCase scrut bndr _ [(DataAlt dc, [bind1, bind2], rhs)])
--
-- Note that it does not matter losing the void-rep thing from the
-- envt (it won't be bound now) because we never look such things up.
- , Just res <- case () of
- _ | isVoidTy rep_ty1 && not (isVoidTy rep_ty2)
+ , Just res <- case (typePrimRep (idType bind1), typePrimRep (idType bind2)) of
+ ([], [_])
-> Just $ doCase d s p scrut bind2 [(DEFAULT, [], rhs)] (Just bndr)
- | isVoidTy rep_ty2 && not (isVoidTy rep_ty1)
+ ([_], [])
-> Just $ doCase d s p scrut bind1 [(DEFAULT, [], rhs)] (Just bndr)
- | otherwise
- -> Nothing
+ _ -> Nothing
= res
schemeE d s p (AnnCase scrut bndr _ [(DataAlt dc, [bind1], rhs)])
| isUnboxedTupleCon dc
- , repTypeArgs (idType bndr) `lengthIs` 1 -- handles unit tuples
+ , length (typePrimRep (idType bndr)) <= 1 -- handles unit tuples
= doCase d s p scrut bind1 [(DEFAULT, [], rhs)] (Just bndr)
schemeE d s p (AnnCase scrut bndr _ alt@[(DEFAULT, [], _)])
| isUnboxedTupleType (idType bndr)
- , [ty] <- repTypeArgs (idType bndr)
+ , Just ty <- case typePrimRep (idType bndr) of
+ [_] -> Just (unwrapType (idType bndr))
+ [] -> Just voidPrimTy
+ _ -> Nothing
-- handles any pattern with a single non-void binder; in particular I/O
-- monad returns (# RealWorld#, a #)
= doCase d s p scrut (bndr `setIdType` ty) alt (Just bndr)
@@ -793,7 +793,7 @@ doCase :: Word -> Sequel -> BCEnv
-> Maybe Id -- Just x <=> is an unboxed tuple case with scrut binder, don't enter the result
-> BcM BCInstrList
doCase d s p (_,scrut) bndr alts is_unboxed_tuple
- | repTypeArgs (idType bndr) `lengthExceeds` 1
+ | typePrimRep (idType bndr) `lengthExceeds` 1
= multiValException
| otherwise
= do
@@ -970,7 +970,7 @@ generateCCall d0 s p (CCallSpec target cconv safety) fn args_r_to_l
pargs _ [] = return []
pargs d (a:az)
- = let [arg_ty] = repTypeArgs (exprType (deAnnotate' a))
+ = let arg_ty = unwrapType (exprType (deAnnotate' a))
in case tyConAppTyCon_maybe arg_ty of
-- Don't push the FO; instead push the Addr# it
@@ -1195,24 +1195,22 @@ maybe_getCCallReturnRep :: Type -> Maybe PrimRep
maybe_getCCallReturnRep fn_ty
= let
(_a_tys, r_ty) = splitFunTys (dropForAlls fn_ty)
- r_reps = repTypeArgs r_ty
+ r_reps = typePrimRepArgs r_ty
blargh :: a -- Used at more than one type
blargh = pprPanic "maybe_getCCallReturn: can't handle:"
(pprType fn_ty)
in
case r_reps of
- [] -> panic "empty repTypeArgs"
- [ty]
- | typePrimRep ty == PtrRep
- -> blargh
- | isVoidTy ty
- -> Nothing
- | otherwise
- -> Just (typePrimRep ty)
+ [] -> panic "empty typePrimRepArgs"
+ [VoidRep] -> Nothing
+ [rep]
+ | isGcPtrRep rep -> blargh
+ | otherwise -> Just rep
+
-- if it was, it would be impossible to create a
-- valid return value placeholder on the stack
- _ -> blargh
+ _ -> blargh
maybe_is_tagToEnum_call :: AnnExpr' Id DVarSet -> Maybe (AnnExpr' Id DVarSet, [Name])
-- Detect and extract relevant info for the tagToEnum kludge.
@@ -1224,7 +1222,7 @@ maybe_is_tagToEnum_call app
= Nothing
where
extract_constr_Names ty
- | [rep_ty] <- repTypeArgs ty
+ | rep_ty <- unwrapType ty
, Just tyc <- tyConAppTyCon_maybe rep_ty
, isDataTyCon tyc
= map (getName . dataConWorkId) (tyConDataCons tyc)
@@ -1331,8 +1329,7 @@ pushAtom d p (AnnCase (_, a) _ _ []) -- trac #12128
= pushAtom d p a
pushAtom d p (AnnVar v)
- | [rep_ty] <- repTypeArgs (idType v)
- , V <- typeArgRep rep_ty
+ | [] <- typePrimRep (idType v)
= return (nilOL, 0)
| isFCallId v
@@ -1542,7 +1539,11 @@ bcIdArgRep :: Id -> ArgRep
bcIdArgRep = toArgRep . bcIdPrimRep
bcIdPrimRep :: Id -> PrimRep
-bcIdPrimRep = typePrimRep . bcIdUnaryType
+bcIdPrimRep id
+ | [rep] <- typePrimRepArgs (idType id)
+ = rep
+ | otherwise
+ = pprPanic "bcIdPrimRep" (ppr id <+> dcolon <+> ppr (idType id))
isFollowableArg :: ArgRep -> Bool
isFollowableArg P = True
@@ -1552,11 +1553,6 @@ isVoidArg :: ArgRep -> Bool
isVoidArg V = True
isVoidArg _ = False
-bcIdUnaryType :: Id -> UnaryType
-bcIdUnaryType x = case repTypeArgs (idType x) of
- [rep_ty] -> rep_ty
- _ -> pprPanic "bcIdUnaryType" (ppr x $$ ppr (idType x))
-
-- See bug #1257
multiValException :: a
multiValException = throwGhcException (ProgramError
@@ -1625,12 +1621,12 @@ isVAtom _ = False
atomPrimRep :: AnnExpr' Id ann -> PrimRep
atomPrimRep e | Just e' <- bcView e = atomPrimRep e'
atomPrimRep (AnnVar v) = bcIdPrimRep v
-atomPrimRep (AnnLit l) = typePrimRep (literalType l)
+atomPrimRep (AnnLit l) = typePrimRep1 (literalType l)
-- Trac #12128:
-- A case expresssion can be an atom because empty cases evaluate to bottom.
-- See Note [Empty case alternatives] in coreSyn/CoreSyn.hs
-atomPrimRep (AnnCase _ _ ty _) = ASSERT(typePrimRep ty == PtrRep) PtrRep
+atomPrimRep (AnnCase _ _ ty _) = ASSERT(typePrimRep ty == [LiftedRep]) LiftedRep
atomPrimRep (AnnCoercion {}) = VoidRep
atomPrimRep other = pprPanic "atomPrimRep" (ppr (deAnnotate' other))
@@ -1648,7 +1644,7 @@ mkStackOffsets original_depth szsw
= map (subtract 1) (tail (scanl (+) original_depth szsw))
typeArgRep :: Type -> ArgRep
-typeArgRep = toArgRep . typePrimRep
+typeArgRep = toArgRep . typePrimRep1
-- -----------------------------------------------------------------------------
-- The bytecode generator's monad
diff --git a/compiler/ghci/ByteCodeItbls.hs b/compiler/ghci/ByteCodeItbls.hs
index 4a4a03913d..6dc89e1d9d 100644
--- a/compiler/ghci/ByteCodeItbls.hs
+++ b/compiler/ghci/ByteCodeItbls.hs
@@ -16,7 +16,7 @@ import HscTypes
import Name ( Name, getName )
import NameEnv
import DataCon ( DataCon, dataConRepArgTys, dataConIdentity )
-import TyCon ( TyCon, tyConFamilySize, isDataTyCon, tyConDataCons, isVoidRep )
+import TyCon ( TyCon, tyConFamilySize, isDataTyCon, tyConDataCons )
import RepType
import StgCmmLayout ( mkVirtConstrSizes )
import StgCmmClosure ( tagForCon, NonVoid (..) )
@@ -56,9 +56,7 @@ make_constr_itbls hsc_env cons =
mk_itbl dcon conNo = do
let rep_args = [ NonVoid prim_rep
| arg <- dataConRepArgTys dcon
- , slot_ty <- repTypeSlots (repType arg)
- , let prim_rep = slotPrimRep slot_ty
- , not (isVoidRep prim_rep) ]
+ , prim_rep <- typePrimRep arg ]
(tot_wds, ptr_wds) =
mkVirtConstrSizes dflags rep_args
diff --git a/compiler/ghci/Debugger.hs b/compiler/ghci/Debugger.hs
index 64ac1540aa..4d7f8e3ef0 100644
--- a/compiler/ghci/Debugger.hs
+++ b/compiler/ghci/Debugger.hs
@@ -28,7 +28,6 @@ import Var hiding ( varName )
import VarSet
import UniqFM
import Type
-import Kind
import GHC
import Outputable
import PprTyThing
@@ -78,7 +77,7 @@ pprintClosureCommand bindThings force str = do
term_ <- GHC.obtainTermFromId maxBound force id'
term <- tidyTermTyVars term_
term' <- if bindThings &&
- False == isUnliftedTypeKind (termType term)
+ (not (isUnliftedType (termType term)))
then bindSuspensions term
else return term
-- Before leaving, we compare the type obtained to see if it's more specific
diff --git a/compiler/ghci/GHCi.hsc b/compiler/ghci/GHCi.hsc
index 4503034971..2354908718 100644
--- a/compiler/ghci/GHCi.hsc
+++ b/compiler/ghci/GHCi.hsc
@@ -641,13 +641,13 @@ wormhole dflags r = wormholeRef dflags (unsafeForeignRefToRemoteRef r)
-- only works when the interpreter is running in the same process as
-- the compiler, so it fails when @-fexternal-interpreter@ is on.
wormholeRef :: DynFlags -> RemoteRef a -> IO a
-wormholeRef dflags r
+wormholeRef dflags _r
| gopt Opt_ExternalInterpreter dflags
= throwIO (InstallationError
"this operation requires -fno-external-interpreter")
#ifdef GHCI
| otherwise
- = localRef r
+ = localRef _r
#else
| otherwise
= throwIO (InstallationError
diff --git a/compiler/ghci/RtClosureInspect.hs b/compiler/ghci/RtClosureInspect.hs
index 815e5e6e0f..03b2f95475 100644
--- a/compiler/ghci/RtClosureInspect.hs
+++ b/compiler/ghci/RtClosureInspect.hs
@@ -735,7 +735,7 @@ cvObtainTerm hsc_env max_depth force old_ty hval = runTR hsc_env $ do
traceTR (text "Following a MutVar")
contents_tv <- newVar liftedTypeKind
contents <- trIO$ IO$ \w -> readMutVar# (unsafeCoerce# a) w
- ASSERT(isUnliftedTypeKind $ typeKind my_ty) return ()
+ ASSERT(isUnliftedType my_ty) return ()
(mutvar_ty,_) <- instScheme $ quantifyType $ mkFunTy
contents_ty (mkTyConApp tycon [world,contents_ty])
addConstraint (mkFunTy contents_tv my_ty) mutvar_ty
@@ -805,9 +805,9 @@ extractSubTerms recurse clos = liftM thdOf3 . go 0 (nonPtrs clos)
(ptr_i, ws, terms1) <- go ptr_i ws tys
return (ptr_i, ws, unboxedTupleTerm ty terms0 : terms1)
| otherwise
- = case repTypeArgs ty of
+ = case typePrimRepArgs ty of
[rep_ty] -> do
- (ptr_i, ws, term0) <- go_rep ptr_i ws ty (typePrimRep rep_ty)
+ (ptr_i, ws, term0) <- go_rep ptr_i ws ty rep_ty
(ptr_i, ws, terms1) <- go ptr_i ws tys
return (ptr_i, ws, term0 : terms1)
rep_tys -> do
@@ -818,18 +818,18 @@ extractSubTerms recurse clos = liftM thdOf3 . go 0 (nonPtrs clos)
go_unary_types ptr_i ws [] = return (ptr_i, ws, [])
go_unary_types ptr_i ws (rep_ty:rep_tys) = do
tv <- newVar liftedTypeKind
- (ptr_i, ws, term0) <- go_rep ptr_i ws tv (typePrimRep rep_ty)
+ (ptr_i, ws, term0) <- go_rep ptr_i ws tv rep_ty
(ptr_i, ws, terms1) <- go_unary_types ptr_i ws rep_tys
return (ptr_i, ws, term0 : terms1)
- go_rep ptr_i ws ty rep = case rep of
- PtrRep -> do
- t <- appArr (recurse ty) (ptrs clos) ptr_i
- return (ptr_i + 1, ws, t)
- _ -> do
- dflags <- getDynFlags
- let (ws0, ws1) = splitAt (primRepSizeW dflags rep) ws
- return (ptr_i, ws1, Prim ty ws0)
+ go_rep ptr_i ws ty rep
+ | isGcPtrRep rep
+ = do t <- appArr (recurse ty) (ptrs clos) ptr_i
+ return (ptr_i + 1, ws, t)
+ | otherwise
+ = do dflags <- getDynFlags
+ let (ws0, ws1) = splitAt (primRepSizeW dflags rep) ws
+ return (ptr_i, ws1, Prim ty ws0)
unboxedTupleTerm ty terms
= Term ty (Right (tupleDataCon Unboxed (length terms)))
@@ -919,17 +919,15 @@ findPtrTys i ty
= findPtrTyss i elem_tys
| otherwise
- = -- Can't directly call repTypeArgs here -- we lose type information in
- -- some cases (e.g. singleton tuples)
- case repType ty of
- UnaryRep rep_ty | typePrimRep rep_ty == PtrRep -> return (i + 1, [(i, ty)])
- | otherwise -> return (i, [])
- MultiRep slot_tys ->
- foldM (\(i, extras) rep_ty ->
- if typePrimRep rep_ty == PtrRep
+ = case typePrimRep ty of
+ [rep] | isGcPtrRep rep -> return (i + 1, [(i, ty)])
+ | otherwise -> return (i, [])
+ prim_reps ->
+ foldM (\(i, extras) prim_rep ->
+ if isGcPtrRep prim_rep
then newVar liftedTypeKind >>= \tv -> return (i + 1, extras ++ [(i, tv)])
else return (i, extras))
- (i, []) (map slotTyToType slot_tys)
+ (i, []) prim_reps
findPtrTyss :: Int
-> [Type]
@@ -955,7 +953,7 @@ getDataConArgTys :: DataCon -> Type -> TR [Type]
--
-- I believe that con_app_ty should not have any enclosing foralls
getDataConArgTys dc con_app_ty
- = do { let UnaryRep rep_con_app_ty = repType con_app_ty
+ = do { let rep_con_app_ty = unwrapType con_app_ty
; traceTR (text "getDataConArgTys 1" <+> (ppr con_app_ty $$ ppr rep_con_app_ty
$$ ppr (tcSplitTyConApp_maybe rep_con_app_ty)))
; (subst, _) <- instTyVars (univ_tvs ++ ex_tvs)
@@ -1193,7 +1191,7 @@ congruenceNewtypes lhs rhs = go lhs rhs >>= \rhs' -> return (lhs,rhs')
text " in presence of newtype evidence " <> ppr new_tycon)
(_, vars) <- instTyVars (tyConTyVars new_tycon)
let ty' = mkTyConApp new_tycon (mkTyVarTys vars)
- UnaryRep rep_ty = repType ty'
+ rep_ty = unwrapType ty'
_ <- liftTcM (unifyType noThing ty rep_ty)
-- assumes that reptype doesn't ^^^^ touch tyconApp args
return ty'
@@ -1235,14 +1233,13 @@ dictsView ty = ty
isMonomorphic :: RttiType -> Bool
isMonomorphic ty = noExistentials && noUniversals
where (tvs, _, ty') = tcSplitSigmaTy ty
- noExistentials = isEmptyVarSet (tyCoVarsOfType ty')
+ noExistentials = noFreeVarsOfType ty'
noUniversals = null tvs
-- Use only for RTTI types
isMonomorphicOnNonPhantomArgs :: RttiType -> Bool
isMonomorphicOnNonPhantomArgs ty
- | UnaryRep rep_ty <- repType ty
- , Just (tc, all_args) <- tcSplitTyConApp_maybe rep_ty
+ | Just (tc, all_args) <- tcSplitTyConApp_maybe (unwrapType ty)
, phantom_vars <- tyConPhantomTyVars tc
, concrete_args <- [ arg | (tyv,arg) <- tyConTyVars tc `zip` all_args
, tyv `notElem` phantom_vars]