DanielG / ghc-syb

Scrap Your Boilerplate instances for GHC's data types
8 stars 10 forks source link

Prelude.undefined when using proc notation #16

Open rubik opened 8 years ago

rubik commented 8 years ago

CC @alanz

Continuing my analysis of Haskell packages, I stumbled upon a weird error with some Pandoc code. Here is the stripped down version of it:

{-# LANGUAGE Arrows #-}

-- | First argument: basis for a new "pretty" anchor if none exists yet
-- Second argument: a key ("ugly" anchor)
-- Returns: saved "pretty" anchor or created new one
getPrettyAnchor :: OdtReaderSafe (AnchorPrefix, Anchor) Anchor
getPrettyAnchor = proc (baseIdent, uglyAnchor) -> do
    state <- getExtraState -< ()
    returnA -< prettyAnchor

While GHC 7.10.2 works as usual, GHC 7.8.4 crashes while traversing the AST. Unlike other times, the program stops with

argon: Prelude.undefined

From my understanding, there should be an undefined somewhere and it's getting evaluated. However, I couldn't find any undefined related to arrows types.

Now I've downloaded the GHC 7.8.4 source code in the hope of finding something with grep.

alanz commented 8 years ago

If I recall some of the landmines were indeed filled with undefined.

I am so glad they are gone from 7.10.2 onwards

On Tue, Nov 3, 2015 at 1:30 PM, Michele Lacchia notifications@github.com wrote:

CC @alanz https://github.com/alanz

Continuing my analysis of Haskell packages, I stumbled upon a weird error with some Pandoc code. Here is the stripped down version of it:

{-# LANGUAGE Arrows #-} -- | First argument: basis for a new "pretty" anchor if none exists yet-- Second argument: a key ("ugly" anchor)-- Returns: saved "pretty" anchor or created new onegetPrettyAnchor :: OdtReaderSafe (AnchorPrefix, Anchor) Anchor getPrettyAnchor = proc (baseIdent, uglyAnchor) -> do state <- getExtraState -< () returnA -< prettyAnchor

While GHC 7.10.2 works as usual, GHC 7.8.4 crashes while traversing the AST. Unlike other times, the program stops with

argon: Prelude.undefined

From my understanding, there should be an undefined somewhere and it's getting evaluated. However, I couldn't find any undefined related to arrows types.

Now I've downloaded the GHC 7.8.4 source code in the hope of finding something with grep.

— Reply to this email directly or view it on GitHub https://github.com/nominolo/ghc-syb/issues/16.

rubik commented 8 years ago

Yeah, they are so annoying. Unfortunately, the grep search (limited to compiler/) did not return anything useful:

$ egrep "^[^-]+?(undefined)" -r compiler/*/**.hs
compiler/cmm/CmmPipeline.hs:refer to undefined LocalRegs, so we must eliminate any unreachable
compiler/cmm/CmmType.hs:(a) Leave the upper bits undefined.  Comparison operations must
compiler/ghci/RtClosureInspect.hs:  go max_depth _ _ _ | seq max_depth False = undefined
compiler/nativeGen/PIC.hs:        = panic "PositionIndependentCode.picRelative undefined for this platform"
compiler/utils/BufWrite.hs:#define STRICT2(f) f a b | a `seq` b `seq` False = undefined
compiler/utils/BufWrite.hs:#define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined
compiler/utils/BufWrite.hs:  where loop _ i | i `seq` False = undefined
compiler/utils/Serialized.hs:  | the_type == typeOf (undefined :: a) = Just (deserialize bytes)
compiler/utils/Serialized.hs:                                     (repConstr (dataTypeOf (undefined :: a)) constr_rep)
compiler/utils/Serialized.hs:deserializeFixedWidthNum bytes k = go (bitSize (undefined :: a)) bytes k
compiler/utils/Serialized.hs:deserializeFixedWidthNum bytes k = go (finiteBitSize (undefined :: a)) bytes k

Couldn't GHC just tell where it encountered the undefined? Something like a traceback would be useful here.

EDIT: Running the code in GHCi and using trace, I was able to get this:

λ> :set -fbreak-on-error
λ> :trace thunk
Stopped at <exception thrown>
_exception :: e = GHC.Exception.SomeException Prelude.undefined

I cannot find that code in GHC source, though.

alanz commented 8 years ago

There are a couple in Parser.y.pp

        | 'proc' aexp '->' exp
                        {% checkPattern empty $2 >>= \ p ->
                            checkCommand $4 >>= \ cmd ->
                            return (LL $ HsProc p (LL $ HsCmdTop cmd
placeHolderType
                                                    placeHolderType
undefined)) }
                                                -- TODO: is LL right here?
acmd    :: { LHsCmdTop RdrName }
        : aexp2                 {% checkCommand $1 >>= \ cmd ->
                                    return (L1 $ HsCmdTop cmd
placeHolderType placeHolderType undefined) }
flattenedpquals :: { Located [LStmt RdrName (LHsExpr RdrName)] }
    : pquals   { case (unLoc $1) of
                    [qs] -> L1 qs
                    -- We just had one thing in our "parallel" list so
                    -- we simply return that thing directly

                    qss -> L1 [L1 $ ParStmt [ParStmtBlock qs undefined
noSyntaxExpr | qs <- qss]
                                            noSyntaxExpr noSyntaxExpr]
                    -- We actually found some actual parallel lists so
                    -- we wrap them into as a ParStmt
                }

On Tue, Nov 3, 2015 at 1:40 PM, Michele Lacchia notifications@github.com wrote:

Yeah, they are so annoying. Unfortunately, the grep search (limited to compiler/) did not return anything useful:

$ compiler/cmm/CmmPipeline.hs:refer to undefined LocalRegs, so we must eliminate any unreachable compiler/cmm/CmmType.hs:(a) Leave the upper bits undefined. Comparison operations must compiler/ghci/RtClosureInspect.hs: go maxdepth | seq maxdepth False = undefined compiler/nativeGen/PIC.hs: = panic "PositionIndependentCode.picRelative undefined for this platform" compiler/utils/BufWrite.hs:#define STRICT2(f) f a b | a seq b seq False = undefined compiler/utils/BufWrite.hs:#define STRICT3(f) f a b c | a seq b seq c seq False = undefined compiler/utils/BufWrite.hs: where loop i | i seq False = undefined compiler/utils/Serialized.hs: | the_type == typeOf (undefined :: a) = Just (deserialize bytes) compiler/utils/Serialized.hs: (repConstr (dataTypeOf (undefined :: a)) constr_rep) compiler/utils/Serialized.hs:deserializeFixedWidthNum bytes k = go (bitSize (undefined :: a)) bytes k compiler/utils/Serialized.hs:deserializeFixedWidthNum bytes k = go (finiteBitSize (undefined :: a)) bytes k

— Reply to this email directly or view it on GitHub https://github.com/nominolo/ghc-syb/issues/16#issuecomment-153327074.

rubik commented 8 years ago

Ahh so it's the last parameter of HsCmdTop which is undefined! It hadn't occurred to me to check the parser code.

rubik commented 8 years ago

Ok, fixing the first two undefined was easy:

diff --git a/src/Argon/SYB/Utils.hs b/src/Argon/SYB/Utils.hs
index 1b780c5..a225a99 100644
--- a/src/Argon/SYB/Utils.hs
+++ b/src/Argon/SYB/Utils.hs
@@ -28,6 +28,7 @@ everythingStaged stage k z f x
       `extQ` postTcType
       `extQ` nameList
       `extQ` coercion
+      `extQ` cmdTable
 #endif
       `extQ` fixity `extQ` nameSet) x = z
   | otherwise = foldl k (f x) (gmapQ (everythingStaged stage k z f) x)
@@ -36,5 +37,6 @@ everythingStaged stage k z f x
         postTcType = const (stage < TypeChecker)               :: PostTcType -> Bool
         nameList   = const (stage < TypeChecker)               :: [Name] -> Bool
         coercion   = const (stage < TypeChecker)               :: Coercion -> Bool
+        cmdTable   = const (stage < TypeChecker)               :: CmdSyntaxTable RdrName -> Bool
 #endif
         fixity     = const (stage < Renamer)                   :: GHC.Fixity -> Bool

I really don't know what happens when stage = Renamer and the type will be CmdSyntaxTable Name. Should we include that case as well? I can confirm that this patch fixes the problem, but I'm only parsing, I don't know if the undefined stays there during the renaming process.

As for the other undefined, it would be nice if we could fix it now even if it never crashed in my tests. However, I don't know how to solve the problem because it is the second parameter of ParStmtBlock, which is a simple list of ids: http://haddock.stackage.org/lts-2.22/ghc-7.8.4/HsExpr.html#t:ParStmtBlock