diff options
author | Richard Eisenberg <rae@cs.brynmawr.edu> | 2016-12-14 21:37:43 -0500 |
---|---|---|
committer | Richard Eisenberg <rae@cs.brynmawr.edu> | 2017-01-19 10:31:52 -0500 |
commit | e7985ed23ddc68b6a2e4af753578dc1d9e8ab4c9 (patch) | |
tree | ba8c4016e218710f8165db92d4b4c10e5559245a /compiler/ghci | |
parent | 38374caa9d6e1373d1b9d335d0f99f3664931fd9 (diff) | |
download | haskell-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.hs | 64 | ||||
-rw-r--r-- | compiler/ghci/ByteCodeItbls.hs | 6 | ||||
-rw-r--r-- | compiler/ghci/Debugger.hs | 3 | ||||
-rw-r--r-- | compiler/ghci/GHCi.hsc | 4 | ||||
-rw-r--r-- | compiler/ghci/RtClosureInspect.hs | 49 |
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] |