Need help with debugging "Impossible case alternative"

Simon Peyton-Jones simonpj at microsoft.com
Mon May 13 22:19:24 CEST 2013


|  When I modified primops to return Int# instead of Bool I assumed that the
|  definition of what
|  is "True" and "False" changes as well. So I changed (prelude/PrelRules.lhs):
|  
|  trueVal, falseVal :: Expr CoreBndr
|  trueVal       = Var trueDataConId
|  falseVal      = Var falseDataConId
|  
|  to:
|  
|  trueVal, falseVal :: DynFlags -> Expr CoreBndr
|  trueVal  dflags = Lit $ onei  dflags
|  falseVal dflags = Lit $ zeroi dflags

That's very dangerous!  You *only* want to do this for the values returned by your primops, not for anything else.  Maybe that's the only way that trueVal, falseVal are used, but I'd change their name to trueValInt, falseValInt, and add a careful comment to explain that they return an expression of type Int# not Bool.

|  I assumed that this is a single source of truth about what is "True" and "False". I
|  just realized
|  that this probably is an incorrect assumption and some parts of the compiler
|  (mostly desugarer?)
|  generate True and False instead of 1# and 0# during the transformations.

And maybe they should! Only your primops return 1#, 0#.  Other uses of True, False should remain unchanged.

|  At the moment I am not sure how deep does this change goes. Should all "True"
|  and "False" values
|  generated by the compiler during transformations be replaced with 1# and 0#

Absolutely not.  Or rather, you'd have to look at each one, and see whether it's generating something that should have type Int#. No substitute for that. Core Lint should be your friend.

Simon


|  
|  Janek
|  
|  Dnia piątek, 10 maja 2013, Simon Peyton-Jones napisał:
|  > It's hard to help without being able to reproduce it.
|  >
|  > | If I understand correctly this means that the case tries to scrutinize
|  > | integer 1 against True and
|  > | False, which obviously fails (surprisingly, compiling with -dcore-lint
|  > | and -dcmm-lint doesn't
|  > | detect any problems).
|  >
|  > That sounds right.  So what is happening right now is that
|  >
|  > 	case 1 of { True -> e1; False -> e2 }
|  >
|  > is getting converted to
|  >
|  > 	error "Missing alternative"
|  >
|  > which isn't much help.  Better perhaps to leave it as
|  > 		case 1 of { True -> e1; False -> e2 }
|  >
|  > and then the next run of CoreLint will complain, and you can see where. You
|  > can do that by replacing the call to missingALt with a call to
|  > reallyRebuildCase env scrut case_bndr alts cont
|  > as in the last equation for rebuildCase
|  >
|  > Then you should get Core Lint errors in the offending library. (Make sure
|  > -dcore-lint is on all the time)
|  >
|  > S
|  >
|  > | -----Original Message-----
|  > | From: ghc-devs-bounces at haskell.org [mailto:ghc-devs-bounces at haskell.org]
|  > | On Behalf Of Jan Stolarek
|  > | Sent: 10 May 2013 11:52
|  > | To: ghc-devs at haskell.org
|  > | Subject: Need help with debugging "Impossible case alternative"
|  > |
|  > | I'm working on modifying comparison primops so that they return Int#
|  > | instead of Bool. I've been
|  > | stuck with one bug for about two weeks now and I just reached a point
|  > | where I don't have any more
|  > | ideas what to do. I would appreciate any hints or ideas.
|  > |
|  > | So far I changed the primops to return Int# and created a module
|  > | GHC.PrimWrappers that contains
|  > | wrappers around the new primops:
|  > |
|  > | (>#) :: Int# -> Int# -> Bool
|  > | (>#) a b = tagToEnum# (a >$# b)  -- (>$#) :: Int# -> Int# -> Int#
|  > |
|  > | I also made changes to base, integer-gmp, primitive and ghc-prim
|  > | libraries
|  > |
|  > | The problem is that many compiled programs produce "Impossible case
|  > | alternative" message when they
|  > | are run. This is generated by missingAlt function, which is called by
|  > | rebuildCase function on
|  > | line 1785 in simplCore/Simplify.lhs. I modified the message displayed by
|  > | missingAlt to get
|  > | information about the scrutinee, binder and case alternatives:
|  > |
|  > | missingAlt env scrut@(LitAlt _) case_bndr alts cont
|  > |   = WARN( True, ptext (sLit "missing LitAlt: ") <+> ppr case_bndr )
|  > |     return (env, mkImpossibleExpr_REMOVE_ME (contResultType cont)
|  > | (showSDoc unsafeGlobalDynFlags $
|  > | ptext (sLit "missing LitAlt : ") <+> ppr scrut <+> ppr case_bndr <+> ppr
|  > | alts))
|  > |
|  > | Here's an example error message:
|  > |
|  > | Impossible case alternative: missing LitAlt :  1 wild [(GHC.Types.False,
|  > | [], GHC.Types.False),
|  > |                           (GHC.Types.True, [], x)]
|  > |
|  > | If I understand correctly this means that the case tries to scrutinize
|  > | integer 1 against True and
|  > | False, which obviously fails (surprisingly, compiling with -dcore-lint
|  > | and -dcmm-lint doesn't
|  > | detect any problems). My theory is that this integer is supposed to be a
|  > | tag of a Bool data type
|  > | (in the example message this would be True) and the call to tagToEnum#
|  > | somehow got eliminated or
|  > | floated out of the case scrutinee. Is that a reasonable theory? Is there
|  > | a transform that could
|  > | perform such floating of tagToEnum# and if so how to prevent it?
|  > |
|  > | I am unable to create a minimal code example that would cause this
|  > | problem. I noticed that the
|  > | problem happens on every attempt to print a floating point number (this
|  > | causes tens of tests in
|  > | the testsuite to fail). I extracted all the code responsible for
|  > | converting Double to String from
|  > | the GHC.Float and GHC.Show modules so that I have a self-contained
|  > | program (except the call to
|  > | print). Surprisingly that extracted code does not produce the error
|  > | message. I'm clueless and
|  > | will really appreciate any ideas.
|  > |
|  > | Janek
|  > |
|  > | _______________________________________________
|  > | ghc-devs mailing list
|  > | ghc-devs at haskell.org
|  > | http://www.haskell.org/mailman/listinfo/ghc-devs
|  



More information about the ghc-devs mailing list