[project @ 2004-10-08 11:35:26 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcSimplify.lhs
index 350e2af..f24b5de 100644 (file)
@@ -21,17 +21,17 @@ module TcSimplify (
 
 import {-# SOURCE #-} TcUnify( unifyTauTy )
 import TcEnv           -- temp
-import HsSyn           ( HsBind(..), LHsBinds, HsExpr(..), LHsExpr, pprLHsBinds )
+import HsSyn           ( HsBind(..), HsExpr(..), LHsExpr, emptyLHsBinds )
 import TcHsSyn         ( TcId, TcDictBinds, mkHsApp, mkHsTyApp, mkHsDictApp )
 
 import TcRnMonad
 import Inst            ( lookupInst, LookupInstResult(..),
-                         tyVarsOfInst, fdPredsOfInsts, fdPredsOfInst, newDicts,
+                         tyVarsOfInst, fdPredsOfInsts, newDicts, 
                          isDict, isClassDict, isLinearInst, linearInstType,
                          isStdClassTyVarDict, isMethodFor, isMethod,
                          instToId, tyVarsOfInsts,  cloneDict,
                          ipNamesOfInsts, ipNamesOfInst, dictPred,
-                         instBindingRequired,
+                         instBindingRequired, fdPredsOfInst,
                          newDictsFromOld, tcInstClassOp,
                          getDictClassTys, isTyVarDict,
                          instLoc, zonkInst, tidyInsts, tidyMoreInsts,
@@ -41,8 +41,8 @@ import Inst           ( lookupInst, LookupInstResult(..),
 import TcEnv           ( tcGetGlobalTyVars, tcLookupId, findGlobals )
 import InstEnv         ( lookupInstEnv, classInstances )
 import TcMType         ( zonkTcTyVarsAndFV, tcInstTyVars, checkAmbiguity )
-import TcType          ( TcTyVar, TcTyVarSet, ThetaType, TyVarDetails(VanillaTv),
-                         mkClassPred, isOverloadedTy, mkTyConApp,
+import TcType          ( TcTyVar, TcTyVarSet, ThetaType, 
+                          mkClassPred, isOverloadedTy, mkTyConApp,
                          mkTyVarTy, tcGetTyVar, isTyVarClassPred, mkTyVarTys,
                          tyVarsOfPred, tcEqType, pprPred )
 import Id              ( idType, mkUserLocal )
@@ -54,7 +54,7 @@ import FunDeps                ( oclose, grow, improve, pprEquationDoc )
 import PrelInfo                ( isNumericClass ) 
 import PrelNames       ( splitName, fstName, sndName, integerTyConName,
                          showClassKey, eqClassKey, ordClassKey )
-import Subst           ( mkTopTyVarSubst, substTheta, substTy )
+import Type            ( zipTopTvSubst, substTheta, substTy )
 import TysWiredIn      ( pairTyCon, doubleTy )
 import ErrUtils                ( Message )
 import VarSet
@@ -651,7 +651,8 @@ inferLoop doc tau_tvs wanteds
          | isClassDict inst              = DontReduceUnlessConstant    -- Dicts
          | otherwise                     = ReduceMe                    -- Lits and Methods
     in
-    traceTc (text "infloop" <+> vcat [ppr tau_tvs', ppr wanteds', ppr preds, ppr (grow preds tau_tvs'), ppr qtvs])     `thenM_`
+    traceTc (text "infloop" <+> vcat [ppr tau_tvs', ppr wanteds', ppr preds, 
+                                     ppr (grow preds tau_tvs'), ppr qtvs])     `thenM_`
                -- Step 2
     reduceContext doc try_me [] wanteds'    `thenM` \ (no_improvement, frees, binds, irreds) ->
 
@@ -765,7 +766,8 @@ tcSimplifyCheck doc qtvs givens wanted_lie
                 givens wanted_lie      `thenM` \ (qtvs', binds) ->
     returnM binds
   where
-    get_qtvs = zonkTcTyVarsAndFV qtvs
+--    get_qtvs = zonkTcTyVarsAndFV qtvs
+    get_qtvs = return (mkVarSet qtvs)
 
 
 -- tcSimplifyInferCheck is used when we know the constraints we are to simplify
@@ -898,8 +900,8 @@ Plan B (cunning, used for a long time up to and including GHC 6.2)
   In the Step 1 this constraint might have been simplified, perhaps to
   (Foo Zero Zero b), AND THEN THAT MIGHT BE IMPROVED, to bind 'b' to 'T'.
   This won't happen in Step 2... but that in turn might prevent some other
-  constraint mentioning 'b' from being simplified... and that in turn
-  breaks the invariant that no constraints are quantified over.
+  constraint (Baz [a] b) being simplified (e.g. via instance Baz [a] T where {..}) 
+  and that in turn breaks the invariant that no constraints are quantified over.
 
   Test typecheck/should_compile/tc177 (which failed in GHC 6.2) demonstrates
   the problem.
@@ -927,7 +929,27 @@ You might think this should work becuase the call to foo gives rise to a constra
 (HasCodedValue t), which can be satisfied by the type sig for doDecodeIO.  But the
 restricted binding act = ... calls tcSimplifyRestricted, and PlanC simplifies the
 constraint using the (rather bogus) instance declaration, and now we are stuffed.
-I claim this is not really a bug.  
+
+I claim this is not really a bug -- but it bit Sergey as well as George.  So here's
+plan D
+
+
+Plan D (a variant of plan B)
+  Step 1: Simplify the constraints as much as possible (to deal 
+  with Plan A's problem), BUT DO NO IMPROVEMENT.  Then set
+       qtvs = tau_tvs \ ftvs( simplify( wanteds ) )
+
+  Step 2: Now simplify again, treating the constraint as 'free' if 
+  it does not mention qtvs, and trying to reduce it otherwise.
+
+  The point here is that it's generally OK to have too few qtvs; that is,
+  to make the thing more monomorphic than it could be.  We don't want to
+  do that in the common cases, but in wierd cases it's ok: the programmer
+  can always add a signature.  
+
+  Too few qtvs => too many wanteds, which is what happens if you do less
+  improvement.
+
 
 \begin{code}
 tcSimplifyRestricted   -- Used for restricted binding groups
@@ -942,31 +964,51 @@ tcSimplifyRestricted      -- Used for restricted binding groups
        -- They are all thrown back in the LIE
 
 tcSimplifyRestricted doc tau_tvs wanteds
-       -- 'reduceMe': Reduce as far as we can.  Don't stop at
+       -- Zonk everything in sight
+  = mappM zonkInst wanteds                     `thenM` \ wanteds' ->
+    zonkTcTyVarsAndFV (varSetElems tau_tvs)    `thenM` \ tau_tvs' ->
+    tcGetGlobalTyVars                          `thenM` \ gbl_tvs' ->
+
+       -- 'reduceMe': Reduce as far as we can.  Don't stop at
        -- dicts; the idea is to get rid of as many type
        -- variables as possible, and we don't want to stop
        -- at (say) Monad (ST s), because that reduces
        -- immediately, with no constraint on s.
-  = simpleReduceLoop doc reduceMe wanteds      `thenM` \ (frees, binds, irreds) ->
-    ASSERT( null frees )
+       --
+       -- BUT do no improvement!  See Plan D above
+    reduceContextWithoutImprovement 
+       doc reduceMe wanteds'           `thenM` \ (_frees, _binds, constrained_dicts) ->
 
        -- Next, figure out the tyvars we will quantify over
-    zonkTcTyVarsAndFV (varSetElems tau_tvs)    `thenM` \ tau_tvs' ->
-    tcGetGlobalTyVars                          `thenM` \ gbl_tvs ->
     let
-       constrained_tvs = tyVarsOfInsts irreds
-       qtvs = (tau_tvs' `minusVarSet` constrained_tvs)
-                        `minusVarSet` oclose (fdPredsOfInsts irreds) gbl_tvs
-               -- The second minusVarSet arranges not to quantify over
-               -- any tyvars that are functionally determined by ones in
-               -- the environment
+       constrained_tvs = tyVarsOfInsts constrained_dicts
+       qtvs = (tau_tvs' `minusVarSet` oclose (fdPredsOfInsts constrained_dicts) gbl_tvs')
+                        `minusVarSet` constrained_tvs
+        try_me inst | isFreeWrtTyVars qtvs inst = Free
+                   | otherwise                 = ReduceMe
     in
     traceTc (text "tcSimplifyRestricted" <+> vcat [
-               pprInsts wanteds, pprInsts frees, pprInsts irreds,
-               pprLHsBinds binds,
+               pprInsts wanteds, pprInsts _frees, pprInsts constrained_dicts,
+               ppr _binds,
                ppr constrained_tvs, ppr tau_tvs', ppr qtvs ])  `thenM_`
 
-    extendLIEs irreds                                          `thenM_`
+       -- The first step may have squashed more methods than
+       -- necessary, so try again, this time more gently, knowing the exact
+       -- set of type variables to quantify over.
+       --
+       -- We quantify only over constraints that are captured by qtvs;
+       -- these will just be a subset of non-dicts.  This in contrast
+       -- to normal inference (using isFreeWhenInferring) in which we quantify over
+       -- all *non-inheritable* constraints too.  This implements choice
+       -- (B) under "implicit parameter and monomorphism" above.
+       --
+       -- Remember that we may need to do *some* simplification, to
+       -- (for example) squash {Monad (ST s)} into {}.  It's not enough
+       -- just to float all constraints
+    reduceContextWithoutImprovement 
+       doc try_me wanteds'             `thenM` \ (frees, binds, irreds) ->
+    ASSERT( null irreds )
+    extendLIEs frees                   `thenM_`
     returnM (varSetElems qtvs, binds)
 \end{code}
 
@@ -1014,7 +1056,7 @@ because the scsel will mess up matching.  Instead we want
        forall dIntegralInt, dNumInt.
        fromIntegral Int Int dIntegralInt dNumInt = id Int
 
-Hence "DontReduce NoSCs"
+Hence "WithoutSCs"
 
 \begin{code}
 tcSimplifyToDicts :: [Inst] -> TcM (TcDictBinds)
@@ -1030,7 +1072,7 @@ tcSimplifyToDicts wanteds
     doc = text "tcSimplifyToDicts"
 
        -- Reduce methods and lits only; stop as soon as we get a dictionary
-    try_me inst        | isDict inst = DontReduce NoSCs        -- See notes above for why NoSCs
+    try_me inst        | isDict inst = KeepDictWithoutSCs      -- See notes above re "WithoutSCs"
                | otherwise   = ReduceMe
 \end{code}
 
@@ -1130,30 +1172,37 @@ For each method @Inst@ in the @init_lie@ that mentions one of the
 @LIE@), as well as the @HsBinds@ generated.
 
 \begin{code}
-bindInstsOfLocalFuns ::        [Inst] -> [TcId] -> TcM (LHsBinds TcId)
+bindInstsOfLocalFuns ::        [Inst] -> [TcId] -> TcM TcDictBinds
+-- Simlifies only MethodInsts, and generate only bindings of form 
+--     fm = f tys dicts
+-- We're careful not to even generate bindings of the form
+--     d1 = d2
+-- You'd think that'd be fine, but it interacts with what is
+-- arguably a bug in Match.tidyEqnInfo (see notes there)
 
 bindInstsOfLocalFuns wanteds local_ids
   | null overloaded_ids
        -- Common case
   = extendLIEs wanteds         `thenM_`
-    returnM emptyBag
+    returnM emptyLHsBinds
 
   | otherwise
-  = simpleReduceLoop doc try_me wanteds                `thenM` \ (frees, binds, irreds) ->
+  = simpleReduceLoop doc try_me for_me `thenM` \ (frees, binds, irreds) ->
     ASSERT( null irreds )
+    extendLIEs not_for_me      `thenM_`
     extendLIEs frees           `thenM_`
     returnM binds
   where
     doc                     = text "bindInsts" <+> ppr local_ids
     overloaded_ids   = filter is_overloaded local_ids
     is_overloaded id = isOverloadedTy (idType id)
+    (for_me, not_for_me) = partition (isMethodFor overloaded_set) wanteds
 
     overloaded_set = mkVarSet overloaded_ids   -- There can occasionally be a lot of them
                                                -- so it's worth building a set, so that
                                                -- lookup (in isMethodFor) is faster
-
-    try_me inst | isMethodFor overloaded_set inst = ReduceMe
-               | otherwise                       = Free
+    try_me inst | isMethod inst = ReduceMe
+               | otherwise     = Free
 \end{code}
 
 
@@ -1174,7 +1223,8 @@ data WhatToDo
                        -- produce an error message of any kind.
                        -- It might be quite legitimate such as (Eq a)!
 
- | DontReduce WantSCs          -- Return as irreducible
+ | KeepDictWithoutSCs  -- Return as irreducible; don't add its superclasses
+                       -- Rather specialised: see notes with tcSimplifyToDicts
 
  | DontReduceUnlessConstant    -- Return as irreducible unless it can
                                -- be reduced to a constant in one step
@@ -1192,6 +1242,7 @@ data WantSCs = NoSCs | AddSCs     -- Tells whether we should add the superclasses
 
 \begin{code}
 type Avails = FiniteMap Inst Avail
+emptyAvails = emptyFM
 
 data Avail
   = IsFree             -- Used for free Insts
@@ -1432,7 +1483,7 @@ reduceContext doc try_me givens wanteds
             ]))                                        `thenM_`
 
         -- Build the Avail mapping from "givens"
-    foldlM addGiven emptyFM givens                     `thenM` \ init_state ->
+    foldlM addGiven emptyAvails givens                 `thenM` \ init_state ->
 
         -- Do the real work
     reduceList (0,[]) try_me wanteds init_state                `thenM` \ avails ->
@@ -1457,23 +1508,60 @@ reduceContext doc try_me givens wanteds
 
     returnM (no_improvement, frees, binds, irreds)
 
+-- reduceContextWithoutImprovement differs from reduceContext
+--     (a) no improvement
+--     (b) 'givens' is assumed empty
+reduceContextWithoutImprovement doc try_me wanteds
+  =
+    traceTc (text "reduceContextWithoutImprovement" <+> (vcat [
+            text "----------------------",
+            doc,
+            text "wanted" <+> ppr wanteds,
+            text "----------------------"
+            ]))                                        `thenM_`
+
+        -- Do the real work
+    reduceList (0,[]) try_me wanteds emptyAvails       `thenM` \ avails ->
+    extractResults avails wanteds                      `thenM` \ (binds, irreds, frees) ->
+
+    traceTc (text "reduceContextWithoutImprovement end" <+> (vcat [
+            text "----------------------",
+            doc,
+            text "wanted" <+> ppr wanteds,
+            text "----",
+            text "avails" <+> pprAvails avails,
+            text "frees" <+> ppr frees,
+            text "----------------------"
+            ]))                                        `thenM_`
+
+    returnM (frees, binds, irreds)
+
 tcImprove :: Avails -> TcM Bool                -- False <=> no change
 -- Perform improvement using all the predicates in Avails
 tcImprove avails
- =  tcGetInstEnvs                      `thenM` \ (home_ie, pkg_ie) ->
+ =  tcGetInstEnvs                      `thenM` \ inst_envs -> 
     let
        preds = [ (pred, pp_loc)
-               | inst <- keysFM avails,
-                 let pp_loc = pprInstLoc (instLoc inst),
-                 pred <- fdPredsOfInst inst
+               | (inst, avail) <- fmToList avails,
+                 pred <- get_preds inst avail,
+                 let pp_loc = pprInstLoc (instLoc inst)
                ]
                -- Avails has all the superclasses etc (good)
                -- It also has all the intermediates of the deduction (good)
                -- It does not have duplicates (good)
                -- NB that (?x::t1) and (?x::t2) will be held separately in avails
                --    so that improve will see them separate
+
+       -- For free Methods, we want to take predicates from their context,
+       -- but for Methods that have been squished their context will already
+       -- be in Avails, and we don't want duplicates.  Hence this rather
+       -- horrid get_preds function
+       get_preds inst IsFree = fdPredsOfInst inst
+       get_preds inst other | isDict inst = [dictPred inst]
+                            | otherwise   = []
+
        eqns = improve get_insts preds
-       get_insts clas = classInstances home_ie clas ++ classInstances pkg_ie clas
+       get_insts clas = classInstances inst_envs clas
      in
      if null eqns then
        returnM True
@@ -1482,10 +1570,11 @@ tcImprove avails
         mappM_ unify eqns      `thenM_`
        returnM False
   where
-    unify ((qtvs, t1, t2), doc)
-        = addErrCtxt doc                               $
-          tcInstTyVars VanillaTv (varSetElems qtvs)    `thenM` \ (_, _, tenv) ->
-          unifyTauTy (substTy tenv t1) (substTy tenv t2)
+    unify ((qtvs, pairs), doc)
+        = addErrCtxt doc                       $
+          tcInstTyVars (varSetElems qtvs)      `thenM` \ (_, _, tenv) ->
+          mapM_ (unif_pr tenv) pairs
+    unif_pr tenv (ty1,ty2) =  unifyTauTy (substTy tenv ty1) (substTy tenv ty2)
 \end{code}
 
 The main context-reduction function is @reduce@.  Here's its game plan.
@@ -1548,7 +1637,7 @@ reduce stack try_me wanted avails
   | otherwise
   = case try_me wanted of {
 
-      DontReduce want_scs -> addIrred want_scs avails wanted
+      KeepDictWithoutSCs -> addIrred NoSCs avails wanted
 
     ; DontReduceUnlessConstant ->    -- It's irreducible (or at least should not be reduced)
                                     -- First, see if the inst can be reduced to a constant in one step
@@ -1692,7 +1781,7 @@ addSCs is_loop avails dict
   where
     (clas, tys) = getDictClassTys dict
     (tyvars, sc_theta, sc_sels, _) = classBigSig clas
-    sc_theta' = substTheta (mkTopTyVarSubst tyvars tys) sc_theta
+    sc_theta' = substTheta (zipTopTvSubst tyvars tys) sc_theta
 
     add_sc avails (sc_dict, sc_sel)    -- Add it, and its superclasses
       | add_me sc_dict = addSCs is_loop avails' sc_dict
@@ -2036,11 +2125,11 @@ tcSimplifyDeriv :: [TyVar]
                -> TcM ThetaType        -- Needed
 
 tcSimplifyDeriv tyvars theta
-  = tcInstTyVars VanillaTv tyvars                      `thenM` \ (tvs, _, tenv) ->
+  = tcInstTyVars tyvars                        `thenM` \ (tvs, _, tenv) ->
        -- The main loop may do unification, and that may crash if 
        -- it doesn't see a TcTyVar, so we have to instantiate. Sigh
        -- ToDo: what if two of them do get unified?
-    newDicts DataDeclOrigin (substTheta tenv theta)    `thenM` \ wanteds ->
+    newDicts DerivOrigin (substTheta tenv theta)       `thenM` \ wanteds ->
     simpleReduceLoop doc reduceMe wanteds              `thenM` \ (frees, _, irreds) ->
     ASSERT( null frees )                       -- reduceMe never returns Free
 
@@ -2072,7 +2161,7 @@ tcSimplifyDeriv tyvars theta
          -- of problems; in particular, it's hard to compare solutions for
          -- equality when finding the fixpoint.  So I just rule it out for now.
   
-       rev_env = mkTopTyVarSubst tvs (mkTyVarTys tyvars)
+       rev_env = zipTopTvSubst tvs (mkTyVarTys tyvars)
                -- This reverse-mapping is a Royal Pain, 
                -- but the result should mention TyVars not TcTyVars
     in
@@ -2094,7 +2183,7 @@ tcSimplifyDefault :: ThetaType    -- Wanted; has no type variables in it
                  -> TcM ()
 
 tcSimplifyDefault theta
-  = newDicts DataDeclOrigin theta              `thenM` \ wanteds ->
+  = newDicts DefaultOrigin theta               `thenM` \ wanteds ->
     simpleReduceLoop doc reduceMe wanteds      `thenM` \ (frees, _, irreds) ->
     ASSERT( null frees )       -- try_me never returns Free
     addNoInstanceErrs Nothing []  irreds       `thenM_`
@@ -2250,7 +2339,7 @@ addTopAmbigErrs dicts
     report :: [(Inst,[TcTyVar])] -> TcM ()
     report pairs@((inst,tvs) : _)      -- The pairs share a common set of ambiguous tyvars
        = mkMonomorphismMsg tidy_env dicts      `thenM` \ (tidy_env, mono_msg) ->
-         addSrcSpan (instLocSrcSpan (instLoc inst)) $
+         setSrcSpan (instLocSrcSpan (instLoc inst)) $
                -- the location of the first one will do for the err message
          addErrTcM (tidy_env, msg $$ mono_msg)
        where