[project @ 2003-09-23 15:10:23 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcSimplify.lhs
index 999d390..1970ab3 100644 (file)
@@ -9,7 +9,8 @@
 module TcSimplify (
        tcSimplifyInfer, tcSimplifyInferCheck,
        tcSimplifyCheck, tcSimplifyRestricted,
-       tcSimplifyToDicts, tcSimplifyIPs, tcSimplifyTop,
+       tcSimplifyToDicts, tcSimplifyIPs, 
+       tcSimplifyTop, tcSimplifyInteractive,
        tcSimplifyBracket,
 
        tcSimplifyDeriv, tcSimplifyDefault,
@@ -32,7 +33,7 @@ import Inst           ( lookupInst, LookupInstResult(..),
                          isStdClassTyVarDict, isMethodFor, isMethod,
                          instToId, tyVarsOfInsts,  cloneDict,
                          ipNamesOfInsts, ipNamesOfInst, dictPred,
-                         instBindingRequired, instCanBeGeneralised,
+                         instBindingRequired,
                          newDictsFromOld, tcInstClassOp,
                          getDictClassTys, isTyVarDict,
                          instLoc, zonkInst, tidyInsts, tidyMoreInsts,
@@ -50,10 +51,11 @@ import Id           ( idType, mkUserLocal )
 import Var             ( TyVar )
 import Name            ( getOccName, getSrcLoc )
 import NameSet         ( NameSet, mkNameSet, elemNameSet )
-import Class           ( classBigSig )
+import Class           ( classBigSig, classKey )
 import FunDeps         ( oclose, grow, improve, pprEquationDoc )
-import PrelInfo                ( isNumericClass, isCreturnableClass, isCcallishClass ) 
-import PrelNames       ( splitName, fstName, sndName )
+import PrelInfo                ( isNumericClass ) 
+import PrelNames       ( splitName, fstName, sndName, showClassKey, eqClassKey, ordClassKey)
+import HscTypes                ( GhciMode(Interactive) )
 
 import Subst           ( mkTopTyVarSubst, substTheta, substTy )
 import TysWiredIn      ( unitTy, pairTyCon )
@@ -63,6 +65,7 @@ import VarEnv         ( TidyEnv )
 import FiniteMap
 import Outputable
 import ListSetOps      ( equivClasses )
+import Unique          ( hasKey )
 import Util            ( zipEqual, isSingleton )
 import List            ( partition )
 import CmdLineOpts
@@ -549,9 +552,6 @@ tcSimplifyInfer doc tau_tvs wanted_lie
   = inferLoop doc (varSetElems tau_tvs)
              wanted_lie                `thenM` \ (qtvs, frees, binds, irreds) ->
 
-       -- Check for non-generalisable insts
-    mappM_ addCantGenErr (filter (not . instCanBeGeneralised) irreds)  `thenM_`
-
     extendLIEs frees                                                   `thenM_`
     returnM (qtvs, binds, map instToId irreds)
 
@@ -1078,6 +1078,7 @@ data Avail
 
   | NoRhs              -- Used for Insts like (CCallable f)
                        -- where no witness is required.
+                       -- ToDo: remove?
 
   | Rhs                -- Used when there is a RHS
        TcExpr          -- The RHS
@@ -1427,8 +1428,13 @@ reduce stack try_me wanted state
     ; ReduceMe ->              -- It should be reduced
        lookupInst wanted             `thenM` \ lookup_result ->
        case lookup_result of
-           GenInst wanteds' rhs -> reduceList stack try_me wanteds' state      `thenM` \ state' ->
-                                   addWanted state' wanted rhs wanteds'
+           GenInst wanteds' rhs -> addWanted state wanted rhs wanteds'         `thenM` \ state' ->
+                                   reduceList stack try_me wanteds' state'
+               -- Experiment with doing addWanted *before* the reduceList, 
+               -- which has the effect of adding the thing we are trying
+               -- to prove to the database before trying to prove the things it
+               -- needs.  See note [RECURSIVE DICTIONARIES]
+
            SimpleInst rhs       -> addWanted state wanted rhs []
 
            NoInstance ->    -- No such instance!
@@ -1596,6 +1602,42 @@ Now we implement the Right Solution, which is to check for loops directly
 when adding superclasses.  It's a bit like the occurs check in unification.
 
 
+Note [RECURSIVE DICTIONARIES]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider 
+    data D r = ZeroD | SuccD (r (D r));
+    
+    instance (Eq (r (D r))) => Eq (D r) where
+        ZeroD     == ZeroD     = True
+        (SuccD a) == (SuccD b) = a == b
+        _         == _         = False;
+    
+    equalDC :: D [] -> D [] -> Bool;
+    equalDC = (==);
+
+We need to prove (Eq (D [])).  Here's how we go:
+
+       d1 : Eq (D [])
+
+by instance decl, holds if
+       d2 : Eq [D []]
+       where   d1 = dfEqD d2
+
+by instance decl of Eq, holds if
+       d3 : D []
+       where   d2 = dfEqList d2
+               d1 = dfEqD d2
+
+But now we can "tie the knot" to give
+
+       d3 = d1
+       d2 = dfEqList d2
+       d1 = dfEqD d2
+
+and it'll even run!  The trick is to put the thing we are trying to prove
+(in this case Eq (D []) into the database before trying to prove its
+contributing clauses.
+       
 
 %************************************************************************
 %*                                                                     *
@@ -1618,10 +1660,14 @@ It's OK: the final zonking stage should zap y to (), which is fine.
 
 
 \begin{code}
-tcSimplifyTop :: [Inst] -> TcM TcDictBinds
+tcSimplifyTop, tcSimplifyInteractive :: [Inst] -> TcM TcDictBinds
+tcSimplifyTop         wanteds = tc_simplify_top False {- Not interactive loop -} wanteds
+tcSimplifyInteractive wanteds = tc_simplify_top True  {- Interactive loop -}     wanteds
+
+
 -- The TcLclEnv should be valid here, solely to improve
 -- error message generation for the monomorphism restriction
-tcSimplifyTop wanteds
+tc_simplify_top is_interactive wanteds
   = getLclEnv                                                  `thenM` \ lcl_env ->
     traceTc (text "tcSimplifyTop" <+> ppr (lclEnvElts lcl_env))        `thenM_`
     simpleReduceLoop (text "tcSimplTop") reduceMe wanteds      `thenM` \ (frees, binds, irreds) ->
@@ -1646,8 +1692,12 @@ tcSimplifyTop wanteds
        (tidy_env, tidy_dicts) = tidyInsts bad_guys
        (bad_ips, non_ips)     = partition isIPDict tidy_dicts
        (no_insts, ambigs)     = partition no_inst non_ips
-       no_inst d = not (isTyVarDict d) || tyVarsOfInst d `subVarSet` fixed_tvs
-       fixed_tvs = oclose (fdPredsOfInsts tidy_dicts) emptyVarSet
+       no_inst d              = not (isTyVarDict d) 
+       -- Previously, there was a more elaborate no_inst definition:
+       --      no_inst d = not (isTyVarDict d) || tyVarsOfInst d `subVarSet` fixed_tvs
+       --      fixed_tvs = oclose (fdPredsOfInsts tidy_dicts) emptyVarSet
+       -- But that seems over-elaborate to me; it only bites for class decls with
+       -- fundeps like this:           class C a b | -> b where ...
     in
 
        -- Report definite errors
@@ -1668,7 +1718,7 @@ tcSimplifyTop wanteds
        addTopAmbigErrs (tidy_env, ambigs)      `thenM_`
 
        -- Disambiguate the ones that look feasible
-        mappM disambigGroup std_oks
+        mappM (disambigGroup is_interactive) std_oks
     )                                  `thenM` \ binds_ambig ->
 
     returnM (binds `andMonoBinds` andMonoBindList binds_ambig)
@@ -1715,15 +1765,12 @@ Since we're not using the result of @foo@, the result if (presumably)
 @void@.
 
 \begin{code}
-disambigGroup :: [Inst]        -- All standard classes of form (C a)
+disambigGroup :: Bool  -- True <=> simplifying at top-level interactive loop
+             -> [Inst] -- All standard classes of form (C a)
              -> TcM TcDictBinds
 
-disambigGroup dicts
-  |   any isNumericClass classes       -- Guaranteed all standard classes
-         -- see comment at the end of function for reasons as to
-         -- why the defaulting mechanism doesn't apply to groups that
-         -- include CCallable or CReturnable dicts.
-   && not (any isCcallishClass classes)
+disambigGroup is_interactive dicts
+  |   any std_default_class classes    -- Guaranteed all standard classes
   =    -- THE DICTS OBEY THE DEFAULTABLE CONSTRAINT
        -- SO, TRY DEFAULT TYPES IN ORDER
 
@@ -1746,35 +1793,36 @@ disambigGroup dicts
     in
        -- See if any default works
     tryM (try_default default_tys)     `thenM` \ mb_ty ->
-    case mb_ty of {
-       Left _ ->       -- If not, add an AmbigErr
-                 addTopAmbigErrs (tidyInsts dicts)     `thenM_`
-                 returnM EmptyMonoBinds ;
+    case mb_ty of
+       Left  _                 -> bomb_out
+       Right chosen_default_ty -> choose_default chosen_default_ty
 
-       Right chosen_default_ty ->
+  | otherwise                          -- No defaults
+  = bomb_out
 
-       -- If so, bind the type variable 
+  where
+    tyvar   = get_tv (head dicts)      -- Should be non-empty
+    classes = map get_clas dicts
+
+    std_default_class cls
+      =  isNumericClass cls
+      || (is_interactive && 
+         classKey cls `elem` [showClassKey, eqClassKey, ordClassKey])
+               -- In interactive mode, we default Show a to Show ()
+               -- to avoid graututious errors on "show []"
+
+    choose_default default_ty  -- Commit to tyvar = default_ty
+      =        -- Bind the type variable 
+       unifyTauTy default_ty (mkTyVarTy tyvar) `thenM_`
        -- and reduce the context, for real this time
-    unifyTauTy chosen_default_ty (mkTyVarTy tyvar)     `thenM_`
-    simpleReduceLoop (text "disambig" <+> ppr dicts)
+       simpleReduceLoop (text "disambig" <+> ppr dicts)
                     reduceMe dicts                     `thenM` \ (frees, binds, ambigs) ->
-    WARN( not (null frees && null ambigs), ppr frees $$ ppr ambigs )
-    warnDefault dicts chosen_default_ty                        `thenM_`
-    returnM binds }
-
-  | all isCreturnableClass classes
-  =    -- Default CCall stuff to (); we don't even both to check that () is an
-       -- instance of CReturnable, because we know it is.
-    unifyTauTy (mkTyVarTy tyvar) unitTy        `thenM_`
-    returnM EmptyMonoBinds
-
-  | otherwise -- No defaults
-  = addTopAmbigErrs (tidyInsts dicts)  `thenM_`
-    returnM EmptyMonoBinds
+       WARN( not (null frees && null ambigs), ppr frees $$ ppr ambigs )
+       warnDefault dicts default_ty                    `thenM_`
+       returnM binds
 
-  where
-    tyvar       = get_tv (head dicts)          -- Should be non-empty
-    classes     = map get_clas dicts
+    bomb_out = addTopAmbigErrs (tidyInsts dicts)       `thenM_`
+              returnM EmptyMonoBinds
 \end{code}
 
 [Aside - why the defaulting mechanism is turned off when
@@ -2098,9 +2146,4 @@ reduceDepthErr n stack
          nest 4 (pprInstsInFull stack)]
 
 reduceDepthMsg n stack = nest 4 (pprInstsInFull stack)
-
------------------------------------------------
-addCantGenErr inst
-  = addErrTc (sep [ptext SLIT("Cannot generalise these overloadings (in a _ccall_):"),
-                  nest 4 (ppr inst <+> pprInstLoc (instLoc inst))])
 \end{code}