[commit: ghc] ghc-8.0: Fix bytecode gen to deal with rep-polymorphism (a8d4759)

git at git.haskell.org git at git.haskell.org
Mon Jul 25 18:36:29 UTC 2016


Repository : ssh://git@git.haskell.org/ghc

On branch  : ghc-8.0
Link       : http://ghc.haskell.org/trac/ghc/changeset/a8d4759eb7add57bcee29cc17023f5e900c44f44/ghc

>---------------------------------------------------------------

commit a8d4759eb7add57bcee29cc17023f5e900c44f44
Author: Simon Peyton Jones <simonpj at microsoft.com>
Date:   Thu May 26 14:20:29 2016 +0100

    Fix bytecode gen to deal with rep-polymorphism
    
    When faced runtime-rep-polymorphic code from a pattern-synonym
    matcher, the bytecode generator was treating the result as lifted,
    which it isn't.  The fix is just to treat those rep-polymorphic
    continuations like unlifted types, and add a dummy arg.
    
    Trac #12007 is a case in point.
    
    (cherry picked from commit 0f1e315b9274725c4a2c975f4d06a5c956cf5385)


>---------------------------------------------------------------

a8d4759eb7add57bcee29cc17023f5e900c44f44
 compiler/ghci/ByteCodeGen.hs               | 37 ++++++++++++++++++++----------
 testsuite/tests/ghci/scripts/T12007.hs     |  7 ++++++
 testsuite/tests/ghci/scripts/T12007.script |  3 +++
 testsuite/tests/ghci/scripts/T12007.stdout |  1 +
 testsuite/tests/ghci/scripts/all.T         |  1 +
 5 files changed, 37 insertions(+), 12 deletions(-)

diff --git a/compiler/ghci/ByteCodeGen.hs b/compiler/ghci/ByteCodeGen.hs
index bf11edb..9a78054 100644
--- a/compiler/ghci/ByteCodeGen.hs
+++ b/compiler/ghci/ByteCodeGen.hs
@@ -31,6 +31,7 @@ import Literal
 import PrimOp
 import CoreFVs
 import Type
+import Kind            ( isLiftedTypeKind )
 import DataCon
 import TyCon
 import Util
@@ -486,35 +487,47 @@ schemeE d s p (AnnLet binds (_,body)) = do
      thunk_codes <- sequence compile_binds
      return (alloc_code `appOL` concatOL thunk_codes `appOL` body_code)
 
--- introduce a let binding for a ticked case expression. This rule
+-- Introduce a let binding for a ticked case expression. This rule
 -- *should* only fire when the expression was not already let-bound
 -- (the code gen for let bindings should take care of that).  Todo: we
 -- call exprFreeVars on a deAnnotated expression, this may not be the
 -- best way to calculate the free vars but it seemed like the least
 -- intrusive thing to do
 schemeE d s p exp@(AnnTick (Breakpoint _id _fvs) _rhs)
-   = if isUnliftedType ty
-        then do
-          -- If the result type is unlifted, then we must generate
+   | isLiftedTypeKind (typeKind ty)
+   = do   id <- newId ty
+          -- Todo: is emptyVarSet correct on the next line?
+          let letExp = AnnLet (AnnNonRec id (fvs, exp)) (emptyDVarSet, AnnVar id)
+          schemeE d s p letExp
+
+   | otherwise
+   = do   -- If the result type is not definitely lifted, then we must generate
           --   let f = \s . tick<n> e
           --   in  f realWorld#
           -- When we stop at the breakpoint, _result will have an unlifted
           -- type and hence won't be bound in the environment, but the
           -- breakpoint will otherwise work fine.
+          --
+          -- NB (Trac #12007) this /also/ applies for if (ty :: TYPE r), where
+          --    r :: RuntimeRep is a variable. This can happen in the
+          --    continuations for a pattern-synonym matcher
+          --    match = /\(r::RuntimeRep) /\(a::TYPE r).
+          --            \(k :: Int -> a) \(v::T).
+          --            case v of MkV n -> k n
+          -- Here (k n) :: a :: Type r, so we don't know if it's lifted
+          -- or not; but that should be fine provided we add that void arg.
+
           id <- newId (mkFunTy realWorldStatePrimTy ty)
           st <- newId realWorldStatePrimTy
           let letExp = AnnLet (AnnNonRec id (fvs, AnnLam st (emptyDVarSet, exp)))
                               (emptyDVarSet, (AnnApp (emptyDVarSet, AnnVar id)
                                                     (emptyDVarSet, AnnVar realWorldPrimId)))
           schemeE d s p letExp
-        else do
-          id <- newId ty
-          -- Todo: is emptyVarSet correct on the next line?
-          let letExp = AnnLet (AnnNonRec id (fvs, exp)) (emptyDVarSet, AnnVar id)
-          schemeE d s p letExp
-   where exp' = deAnnotate' exp
-         fvs  = exprFreeVarsDSet exp'
-         ty   = exprType exp'
+
+   where
+     exp' = deAnnotate' exp
+     fvs  = exprFreeVarsDSet exp'
+     ty   = exprType exp'
 
 -- ignore other kinds of tick
 schemeE d s p (AnnTick _ (_, rhs)) = schemeE d s p rhs
diff --git a/testsuite/tests/ghci/scripts/T12007.hs b/testsuite/tests/ghci/scripts/T12007.hs
new file mode 100644
index 0000000..c678727
--- /dev/null
+++ b/testsuite/tests/ghci/scripts/T12007.hs
@@ -0,0 +1,7 @@
+{-# LANGUAGE PatternSynonyms #-}
+module T12007 where
+
+data Foo a = Foo a a
+
+pattern A a1 a2 = Foo a1 a2
+pattern B a1 a2 = A a1 a2
diff --git a/testsuite/tests/ghci/scripts/T12007.script b/testsuite/tests/ghci/scripts/T12007.script
new file mode 100644
index 0000000..8e6a27a
--- /dev/null
+++ b/testsuite/tests/ghci/scripts/T12007.script
@@ -0,0 +1,3 @@
+:l T12007
+let f (B x y) = (y,x)
+f (Foo 'c' 'd')
diff --git a/testsuite/tests/ghci/scripts/T12007.stdout b/testsuite/tests/ghci/scripts/T12007.stdout
new file mode 100644
index 0000000..a6a2425
--- /dev/null
+++ b/testsuite/tests/ghci/scripts/T12007.stdout
@@ -0,0 +1 @@
+('d','c')
diff --git a/testsuite/tests/ghci/scripts/all.T b/testsuite/tests/ghci/scripts/all.T
index 47a775b..a0b5f1b 100755
--- a/testsuite/tests/ghci/scripts/all.T
+++ b/testsuite/tests/ghci/scripts/all.T
@@ -248,3 +248,4 @@ test('T11524a', normal, ghci_script, ['T11524a.script'])
 test('T11456', normal, ghci_script, ['T11456.script'])
 test('TypeAppData', normal, ghci_script, ['TypeAppData.script'])
 test('T11376', normal, ghci_script, ['T11376.script'])
+test('T12007', normal, ghci_script, ['T12007.script'])



More information about the ghc-commits mailing list