diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2017-12-13 10:46:26 +0000 |
---|---|---|
committer | Simon Peyton Jones <simonpj@microsoft.com> | 2017-12-13 10:52:10 +0000 |
commit | e40db7b1676627f5291b463405338e7b69fa3f69 (patch) | |
tree | 8426bae8d6097dcd89fc55282c0167bae33b12b9 /compiler/basicTypes/Id.hs | |
parent | a106a200892e2ac7953f0929c303d392c8808f89 (diff) | |
download | haskell-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.hs | 26 |
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 |