diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2021-04-15 15:20:26 +0100 |
---|---|---|
committer | Simon Peyton Jones <simonpj@microsoft.com> | 2021-04-22 23:29:32 +0100 |
commit | 8d135dfb871662f86b522c6fa337d1695f6bfe1a (patch) | |
tree | f1ac26cda512f01a680f05758fdf7b38f9f46119 /compiler/GHC/Core/Lint.hs | |
parent | 7bc7eea3897dcb8a87fdb0921f451b9bc77309f6 (diff) | |
download | haskell-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.hs | 11 |
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 |