summaryrefslogtreecommitdiff
path: root/compiler/basicTypes/IdInfo.hs
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/basicTypes/IdInfo.hs
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/basicTypes/IdInfo.hs')
-rw-r--r--compiler/basicTypes/IdInfo.hs94
1 files changed, 79 insertions, 15 deletions
diff --git a/compiler/basicTypes/IdInfo.hs b/compiler/basicTypes/IdInfo.hs
index 392c1eca5b..3c6727c8dc 100644
--- a/compiler/basicTypes/IdInfo.hs
+++ b/compiler/basicTypes/IdInfo.hs
@@ -8,6 +8,8 @@
Haskell. [WDP 94/11])
-}
+{-# LANGUAGE CPP #-}
+
module IdInfo (
-- * The IdDetails type
IdDetails(..), pprIdDetails, coVarDetails, isCoVarDetails,
@@ -66,8 +68,14 @@ module IdInfo (
-- ** Tick-box Info
TickBoxOp(..), TickBoxId,
+
+ -- ** Levity info
+ LevityInfo, levityInfo, setNeverLevPoly, setLevityInfoWithType,
+ isNeverLevPolyIdInfo
) where
+#include "HsVersions.h"
+
import CoreSyn
import Class
@@ -78,10 +86,12 @@ import BasicTypes
import DataCon
import TyCon
import PatSyn
+import Type
import ForeignCall
import Outputable
import Module
import Demand
+import Util
-- infixl so you can say (id `set` a `set` b)
infixl 1 `setRuleInfo`,
@@ -92,7 +102,9 @@ infixl 1 `setRuleInfo`,
`setOccInfo`,
`setCafInfo`,
`setStrictnessInfo`,
- `setDemandInfo`
+ `setDemandInfo`,
+ `setNeverLevPoly`,
+ `setLevityInfoWithType`
{-
************************************************************************
@@ -127,7 +139,8 @@ data IdDetails
-- or class operation of a class
| PrimOpId PrimOp -- ^ The 'Id' is for a primitive operator
- | FCallId ForeignCall -- ^ The 'Id' is for a foreign call
+ | FCallId ForeignCall -- ^ The 'Id' is for a foreign call.
+ -- Type will be simple: no type families, newtypes, etc
| TickBoxOpId TickBoxOp -- ^ The 'Id' is for a HPC tick box (both traditional and binary)
@@ -169,18 +182,18 @@ pprIdDetails :: IdDetails -> SDoc
pprIdDetails VanillaId = empty
pprIdDetails other = brackets (pp other)
where
- pp VanillaId = panic "pprIdDetails"
- pp (DataConWorkId _) = text "DataCon"
- pp (DataConWrapId _) = text "DataConWrapper"
- pp (ClassOpId {}) = text "ClassOp"
- pp (PrimOpId _) = text "PrimOp"
- pp (FCallId _) = text "ForeignCall"
- pp (TickBoxOpId _) = text "TickBoxOp"
- pp (DFunId nt) = text "DFunId" <> ppWhen nt (text "(nt)")
+ pp VanillaId = panic "pprIdDetails"
+ pp (DataConWorkId _) = text "DataCon"
+ pp (DataConWrapId _) = text "DataConWrapper"
+ pp (ClassOpId {}) = text "ClassOp"
+ pp (PrimOpId _) = text "PrimOp"
+ pp (FCallId _) = text "ForeignCall"
+ pp (TickBoxOpId _) = text "TickBoxOp"
+ pp (DFunId nt) = text "DFunId" <> ppWhen nt (text "(nt)")
pp (RecSelId { sel_naughty = is_naughty })
- = brackets $ text "RecSel"
- <> ppWhen is_naughty (text "(naughty)")
- pp CoVarId = text "CoVarId"
+ = brackets $ text "RecSel" <>
+ ppWhen is_naughty (text "(naughty)")
+ pp CoVarId = text "CoVarId"
{-
************************************************************************
@@ -221,8 +234,10 @@ data IdInfo
strictnessInfo :: StrictSig, -- ^ A strictness signature
demandInfo :: Demand, -- ^ ID demand information
- callArityInfo :: !ArityInfo -- ^ How this is called.
+ callArityInfo :: !ArityInfo, -- ^ How this is called.
-- n <=> all calls have at least n arguments
+
+ levityInfo :: LevityInfo -- ^ when applied, will this Id ever have a levity-polymorphic type?
}
-- Setters
@@ -272,7 +287,8 @@ vanillaIdInfo
occInfo = NoOccInfo,
demandInfo = topDmd,
strictnessInfo = nopSig,
- callArityInfo = unknownArity
+ callArityInfo = unknownArity,
+ levityInfo = NoLevityInfo
}
-- | More informative 'IdInfo' we can use when we know the 'Id' has no CAF references
@@ -520,3 +536,51 @@ data TickBoxOp
instance Outputable TickBoxOp where
ppr (TickBox mod n) = text "tick" <+> ppr (mod,n)
+
+{-
+************************************************************************
+* *
+ Levity
+* *
+************************************************************************
+
+Note [Levity info]
+~~~~~~~~~~~~~~~~~~
+
+Ids store whether or not they can be levity-polymorphic at any amount
+of saturation. This is helpful in optimizing the levity-polymorphism check
+done in the desugarer, where we can usually learn that something is not
+levity-polymorphic without actually figuring out its type. See
+isExprLevPoly in CoreUtils for where this info is used. Storing
+this is required to prevent perf/compiler/T5631 from blowing up.
+
+-}
+
+-- See Note [Levity info]
+data LevityInfo = NoLevityInfo -- always safe
+ | NeverLevityPolymorphic
+ deriving Eq
+
+instance Outputable LevityInfo where
+ ppr NoLevityInfo = text "NoLevityInfo"
+ ppr NeverLevityPolymorphic = text "NeverLevityPolymorphic"
+
+-- | Marks an IdInfo describing an Id that is never levity polymorphic (even when
+-- applied). The Type is only there for checking that it's really never levity
+-- polymorphic
+setNeverLevPoly :: HasDebugCallStack => IdInfo -> Type -> IdInfo
+setNeverLevPoly info ty
+ = ASSERT2( not (resultIsLevPoly ty), ppr ty )
+ info { levityInfo = NeverLevityPolymorphic }
+
+setLevityInfoWithType :: IdInfo -> Type -> IdInfo
+setLevityInfoWithType info ty
+ | not (resultIsLevPoly ty)
+ = info { levityInfo = NeverLevityPolymorphic }
+ | otherwise
+ = info
+
+isNeverLevPolyIdInfo :: IdInfo -> Bool
+isNeverLevPolyIdInfo info
+ | NeverLevityPolymorphic <- levityInfo info = True
+ | otherwise = False