summaryrefslogtreecommitdiff
path: root/compiler/basicTypes/Id.hs
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2017-12-13 10:46:26 +0000
committerSimon Peyton Jones <simonpj@microsoft.com>2017-12-13 10:52:10 +0000
commite40db7b1676627f5291b463405338e7b69fa3f69 (patch)
tree8426bae8d6097dcd89fc55282c0167bae33b12b9 /compiler/basicTypes/Id.hs
parenta106a200892e2ac7953f0929c303d392c8808f89 (diff)
downloadhaskell-e40db7b1676627f5291b463405338e7b69fa3f69.tar.gz
Detect levity-polymorphic uses of unsafeCoerce#
This bug was shown up by Trac #14561. The deguarer carefully detects unsaturated and levity-polymorphic uses of primops, but not of things like unsafeCoerce#. The fix is simple: see Note [Levity-polymorphic Ids] in Id.
Diffstat (limited to 'compiler/basicTypes/Id.hs')
-rw-r--r--compiler/basicTypes/Id.hs26
1 files changed, 23 insertions, 3 deletions
diff --git a/compiler/basicTypes/Id.hs b/compiler/basicTypes/Id.hs
index 63ca38cb61..fbece0e68d 100644
--- a/compiler/basicTypes/Id.hs
+++ b/compiler/basicTypes/Id.hs
@@ -119,7 +119,8 @@ module Id (
import GhcPrelude
import DynFlags
-import CoreSyn ( CoreRule, isStableUnfolding, evaldUnfolding, Unfolding( NoUnfolding ) )
+import CoreSyn ( CoreRule, isStableUnfolding, evaldUnfolding,
+ isCompulsoryUnfolding, Unfolding( NoUnfolding ) )
import IdInfo
import BasicTypes
@@ -519,7 +520,8 @@ hasNoBinding id = case Var.idDetails id of
PrimOpId _ -> True -- See Note [Primop wrappers]
FCallId _ -> True
DataConWorkId dc -> isUnboxedTupleCon dc || isUnboxedSumCon dc
- _ -> False
+ _ -> isCompulsoryUnfolding (idUnfolding id)
+ -- See Note [Levity-polymorphic Ids]
isImplicitId :: Id -> Bool
-- ^ 'isImplicitId' tells whether an 'Id's info is implied by other
@@ -541,7 +543,25 @@ isImplicitId id
idIsFrom :: Module -> Id -> Bool
idIsFrom mod id = nameIsLocalOrFrom mod (idName id)
-{-
+{- Note [Levity-polymorphic Ids]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Some levity-polymorphic Ids must be applied and and inlined, not left
+un-saturated. Example:
+ unsafeCoerceId :: forall r1 r2 (a::TYPE r1) (b::TYPE r2). a -> b
+
+This has a compulsory unfolding because we can't lambda-bind those
+arguments. But the compulsory unfolding may leave levity-polymorphic
+lambdas if it is not applied to enough arguments; e.g. (Trac #14561)
+ bad :: forall (a :: TYPE r). a -> a
+ bad = unsafeCoerce#
+
+The desugar has special magic to detect such cases: DsExpr.badUseOfLevPolyPrimop.
+And we want that magic to apply to levity-polymorphic compulsory-inline things.
+The easiest way to do this is for hasNoBinding to return True of all things
+that have compulsory unfolding. A very Ids with a compulsory unfolding also
+have a binding, but it does not harm to say they don't here, and its a very
+simple way to fix Trac #14561.
+
Note [Primop wrappers]
~~~~~~~~~~~~~~~~~~~~~~
Currently hasNoBinding claims that PrimOpIds don't have a curried