summaryrefslogtreecommitdiff
path: root/compiler/GHC/Core/Lint.hs
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2021-04-15 15:20:26 +0100
committerSimon Peyton Jones <simonpj@microsoft.com>2021-04-22 23:29:32 +0100
commit8d135dfb871662f86b522c6fa337d1695f6bfe1a (patch)
treef1ac26cda512f01a680f05758fdf7b38f9f46119 /compiler/GHC/Core/Lint.hs
parent7bc7eea3897dcb8a87fdb0921f451b9bc77309f6 (diff)
downloadhaskell-wip/T19700.tar.gz
Eliminate unsafeEqualityProof in CorePrepwip/T19700
The main idea here is to avoid treating * case e of {} * case unsafeEqualityProof of UnsafeRefl co -> blah specially in CoreToStg. Instead, nail them in CorePrep, by converting case e of {} ==> e |> unsafe-co case unsafeEqualityProof of UnsafeRefl cv -> blah ==> blah[unsafe-co/cv] in GHC.Core.Prep. Now expressions that we want to treat as trivial really are trivial. We can get rid of cpExprIsTrivial. And we fix #19700. A downside is that, at least under unsafeEqualityProof, we substitute in types and coercions, which is more work. But a big advantage is that it's all very simple and principled: CorePrep really gets rid of the unsafeCoerce stuff, as it does empty case, runRW#, lazyId etc. I've updated the overview in GHC.Core.Prep, and added Note [Unsafe coercions] in GHC.Core.Prep Note [Implementing unsafeCoerce] in base:Unsafe.Coerce We get 3% fewer bytes allocated when compiling perf/compiler/T5631, which uses a lot of unsafeCoerces. (It's a happy-generated parser.) Metric Decrease: T5631
Diffstat (limited to 'compiler/GHC/Core/Lint.hs')
-rw-r--r--compiler/GHC/Core/Lint.hs11
1 files changed, 10 insertions, 1 deletions
diff --git a/compiler/GHC/Core/Lint.hs b/compiler/GHC/Core/Lint.hs
index 3438f372fc..a5da50bd1d 100644
--- a/compiler/GHC/Core/Lint.hs
+++ b/compiler/GHC/Core/Lint.hs
@@ -2116,7 +2116,8 @@ lintCoercion co@(UnivCo prov r ty1 ty2)
; checkWarnL (not lev_poly2)
(report "right-hand type is levity-polymorphic")
; when (not (lev_poly1 || lev_poly2)) $
- do { checkWarnL (reps1 `equalLength` reps2)
+ do { checkWarnL (reps1 `equalLength` reps2 ||
+ is_core_prep_prov prov)
(report "between values with different # of reps")
; zipWithM_ validateCoercion reps1 reps2 }}
where
@@ -2128,6 +2129,13 @@ lintCoercion co@(UnivCo prov r ty1 ty2)
reps1 = typePrimRep t1
reps2 = typePrimRep t2
+ -- CorePrep deliberately makes ill-kinded casts
+ -- e.g (case error @Int "blah" of {}) :: Int#
+ -- ==> (error @Int "blah") |> Unsafe Int Int#
+ -- See Note [Unsafe coercions] in GHC.Core.CoreToStg.Prep
+ is_core_prep_prov CorePrepProv = True
+ is_core_prep_prov _ = False
+
validateCoercion :: PrimRep -> PrimRep -> LintM ()
validateCoercion rep1 rep2
= do { platform <- targetPlatform <$> getDynFlags
@@ -2158,6 +2166,7 @@ lintCoercion co@(UnivCo prov r ty1 ty2)
; return (ProofIrrelProv kco') }
lint_prov _ _ prov@(PluginProv _) = return prov
+ lint_prov _ _ prov@CorePrepProv = return prov
check_kinds kco k1 k2
= do { let Pair k1' k2' = coercionKind kco