Repository : ssh://darcs.haskell.org//srv/darcs/ghc On branch :
http://hackage.haskell.org/trac/ghc/changeset/ee61318587c576e1f4f4f3371ffd06bd4eeb2492 >--------------------------------------------------------------- commit ee61318587c576e1f4f4f3371ffd06bd4eeb2492 Author: Max Bolingbroke <batterseapo...@hotmail.com> Date: Wed Jan 4 14:21:57 2012 +0000 Fix a horrible matching bug that was causing too many binder pairs to be matched rigidly >--------------------------------------------------------------- compiler/supercompile/Supercompile/Drive/Match.hs | 28 +++++++++++++------- 1 files changed, 18 insertions(+), 10 deletions(-) diff --git a/compiler/supercompile/Supercompile/Drive/Match.hs b/compiler/supercompile/Supercompile/Drive/Match.hs index e1c5419..4ad4317 100644 --- a/compiler/supercompile/Supercompile/Drive/Match.hs +++ b/compiler/supercompile/Supercompile/Drive/Match.hs @@ -31,9 +31,9 @@ import qualified Data.Map as M pprTraceSC :: String -> SDoc -> a -> a -pprTraceSC _ _ = id +--pprTraceSC _ _ = id --pprTraceSC = pprTrace ---pprTraceSC msg doc a = traceSC (msg ++ ": " ++ showSDoc doc) a +pprTraceSC msg doc a = traceSC (msg ++ ": " ++ showSDoc doc) a traceSC :: String -> a -> a traceSC _ = id @@ -122,9 +122,16 @@ match s_l s_r = runMatch (match' s_l s_r) match' :: State -> State -> Match MatchResult -match' s_l@(_deeds_l, Heap h_l _, k_l, qa_l) s_r@(_deeds_r, Heap h_r _, k_r, qa_r) = -- (\res -> traceRender ("match", M.keysSet h_l, residualiseDriveState (Heap h_l prettyIdSupply, k_l, in_e_l), M.keysSet h_r, residualiseDriveState (Heap h_r prettyIdSupply, k_r, in_e_r), res) res) $ +match' (_deeds_l, Heap h_l ids_l, k_l, qa_l) (_deeds_r, Heap h_r ids_r, k_r, qa_r) = -- (\res -> traceRender ("match", M.keysSet h_l, residualiseDriveState (Heap h_l prettyIdSupply, k_l, in_e_l), M.keysSet h_r, residualiseDriveState (Heap h_r prettyIdSupply, k_r, in_e_r), res) res) $ do - let init_rn2 = matchRnEnv2 stateFreeVars s_l s_r + -- It's very important that we don't just use the state free variables from both sides to construct the initial in scope set, + -- because we use it to match the stack and QA on each side *without* first extending it with variables bound by the PureHeap! + -- + -- The InScopeSets from the Heap are guaranteed to take these into account (along with the stuff bound by the stack, but that + -- doesn't matter too much) so we just use those instead. + -- + -- This was the source of a very confusing bug :-( + let init_rn2 = mkRnEnv2 (ids_l `unionInScope` ids_r) (rn2, mfree_eqs2) <- mfix $ \(~(rn2, _)) -> matchEC init_rn2 rn2 k_l k_r free_eqs1 <- pprTraceSC "match0" (rn2 `seq` empty) $ matchAnned (matchQA rn2) qa_l qa_r free_eqs2 <- pprTraceSC "match1" empty $ mfree_eqs2 @@ -240,7 +247,7 @@ checkMatchLR x_l x_r lr = case lr of -- We have to be careful to match the "fragile" IdInfo for binders as well as the obvious type information -- (idSpecialisation :: Id -> SpecInfo, realIdUnfolding :: Id -> Unfolding) matchIdCoVarBndr' :: RnEnv2 -> RnEnv2 {- knot-tied -} -> Id -> Id -> (RnEnv2, Match [MatchLR]) -matchIdCoVarBndr' init_rn2 rn2 x_l x_r = (rnBndr2 init_rn2 x_l x_r, matchIdCoVarBndrExtras rn2 x_l x_r) +matchIdCoVarBndr' init_rn2 rn2 x_l x_r = (pprTraceSC "matchIdCoVarBndr'" (ppr (x_l, x_r)) $ rnBndr2 init_rn2 x_l x_r, matchIdCoVarBndrExtras rn2 x_l x_r) matchBndrExtras :: RnEnv2 -> Var -> Var -> Match [MatchLR] matchBndrExtras rn2 v_l v_r @@ -323,9 +330,9 @@ matchVar rn2 x_l x_r = fmap maybeToList (matchVar_maybe rn2 x_l x_r) matchVar_maybe :: RnEnv2 -> Out Id -> Out Id -> Match (Maybe MatchLR) matchVar_maybe rn2 x_l x_r = case (rnOccL_maybe rn2 x_l, rnOccR_maybe rn2 x_r) of -- Both rigidly bound: match iff they rename to the same thing - (Just x_l', Just x_r') -> guard "matchVar: rigid" (x_l' == x_r') >> return Nothing + (Just x_l', Just x_r') -> pprTraceSC "matchVar_maybe(rigid)" (ppr (x_l, x_r)) $ guard "matchVar: rigid" (x_l' == x_r') >> return Nothing -- Both bound by let: defer decision about matching - (Nothing, Nothing) -> return (Just (VarLR x_l x_r)) + (Nothing, Nothing) -> pprTraceSC "matchVar_maybe(flexi)" (ppr (x_l, x_r)) $ return (Just (VarLR x_l x_r)) -- One bound by let and one bound rigidly: don't match _ -> fail "matchVar: mismatch" @@ -436,9 +443,10 @@ matchPureHeap rn2 init_free_eqs h_l h_r -- NB: it is OK to do exact syntactic equality on VarL/VarR here because we always rename new equalities generated in -- this loop using the same InScopeSet (that from rn2) so only a finite number of distinct binders will be generated. | lr `elem` known = matchLoop known free_eqs used_l used_r - | otherwise = {- traceSC "matchLoop" $ -} case (case lr of VarLR x_l x_r -> (go_template (matchBndrExtras rn2 x_l x_r) , lookupUsed used_l x_l h_l, lookupUsed used_r x_r h_r) - VarL x_l e_r -> (go_template (matchIdCoVarBndrExtrasL rn2 x_l e_r), lookupUsed used_l x_l h_l, Just (InternallyBound, Just (Just (used_r, e_r)))) - VarR e_l x_r -> (go_template (matchIdCoVarBndrExtrasR rn2 e_l x_r), Just (InternallyBound, Just (Just (used_l, e_l))), lookupUsed used_r x_r h_r)) of + | otherwise = pprTraceSC "matchLoop" (ppr lr) $ + case (case lr of VarLR x_l x_r -> (go_template (matchBndrExtras rn2 x_l x_r) , lookupUsed used_l x_l h_l, lookupUsed used_r x_r h_r) + VarL x_l e_r -> (go_template (matchIdCoVarBndrExtrasL rn2 x_l e_r), lookupUsed used_l x_l h_l, Just (InternallyBound, Just (Just (used_r, e_r)))) + VarR e_l x_r -> (go_template (matchIdCoVarBndrExtrasR rn2 e_l x_r), Just (InternallyBound, Just (Just (used_l, e_l))), lookupUsed used_r x_r h_r)) of -- If matching an internal let, it is possible that variables occur free. Insist that free-ness matches: -- TODO: actually I'm pretty sure that the heap binds *everything* now. These cases could probably be removed, -- though they don't do any particular harm. _______________________________________________ Cvs-ghc mailing list Cvs-ghc@haskell.org http://www.haskell.org/mailman/listinfo/cvs-ghc