Check that AT instance is in a class
[ghc-hetmet.git] / compiler / typecheck / TcInstDcls.lhs
index 1aa126f..e12f234 100644 (file)
@@ -22,15 +22,16 @@ import Inst         ( newDictBndr, newDictBndrs, instToId, showLIE,
 import InstEnv         ( mkLocalInstance, instanceDFunId )
 import TcDeriv         ( tcDeriving )
 import TcEnv           ( InstInfo(..), InstBindings(..), 
-                         newDFunName, tcExtendIdEnv
+                         newDFunName, tcExtendIdEnv, tcExtendGlobalEnv
                        )
 import TcHsType                ( kcHsSigType, tcHsKindedType )
 import TcUnify         ( checkSigTyVars )
 import TcSimplify      ( tcSimplifySuperClasses )
 import Type            ( zipOpenTvSubst, substTheta, mkTyConApp, mkTyVarTy,
-                          splitFunTys )
+                          splitFunTys, TyThing(ATyCon) )
 import Coercion         ( mkSymCoercion )
-import TyCon            ( TyCon, newTyConCo, tyConTyVars )
+import TyCon            ( TyCon, tyConName, newTyConCo, tyConTyVars,
+                         isAssocTyCon, tyConFamInst_maybe )
 import DataCon         ( classDataCon, dataConTyCon, dataConInstArgTys )
 import Class           ( classBigSig )
 import Var             ( TyVar, Id, idName, idType, tyVarKind )
@@ -38,12 +39,14 @@ import Id               ( mkSysLocal )
 import UniqSupply       ( uniqsFromSupply, splitUniqSupply )
 import MkId            ( mkDictFunId )
 import Name            ( Name, getSrcLoc )
-import Maybe           ( catMaybes )
+import Maybe           ( isNothing, fromJust, catMaybes )
+import Monad           ( when )
 import SrcLoc          ( srcLocSpan, unLoc, noLoc, Located(..), srcSpanStart )
 import ListSetOps      ( minusList )
 import Outputable
 import Bag
 import BasicTypes      ( Activation( AlwaysActive ), InlineSpec(..) )
+import HscTypes                ( implicitTyThings )
 import FastString
 \end{code}
 
@@ -146,24 +149,35 @@ tcInstDecls1 tycl_decls inst_decls
                -- (1) Do the ordinary instance declarations and instances of
                --     indexed types
        ; let { idxty_decls = filter (isIdxTyDecl . unLoc) tycl_decls }
-       ; local_inst_infos <- mappM tcLocalInstDecl1 inst_decls
-       ; idxty_inst_infos <- mappM tcIdxTyInstDecl idxty_decls
-
-       ; let { local_inst_info = concat local_inst_infos ++ 
-                                catMaybes idxty_inst_infos
-            ; clas_decls      = filter (isClassDecl.unLoc) tycl_decls }
-
-               -- (2) Instances from generic class declarations
+       ; local_info_tycons <- mappM tcLocalInstDecl1  inst_decls
+       ; idxty_info_tycons <- mappM tcIdxTyInstDeclTL idxty_decls
+
+       ; let { (local_infos,
+               local_tycons)    = unzip local_info_tycons
+            ; (idxty_infos, 
+               idxty_tycons)    = unzip idxty_info_tycons
+            ; local_idxty_info  = concat local_infos ++ catMaybes idxty_infos
+            ; local_idxty_tycon = concat local_tycons ++ 
+                                  catMaybes idxty_tycons
+            ; clas_decls        = filter (isClassDecl.unLoc) tycl_decls 
+            ; implicit_things   = concatMap implicitTyThings local_idxty_tycon
+            }
+
+               -- (2) Add the tycons of associated types and their implicit
+               --     tythings to the global environment
+       ; tcExtendGlobalEnv (local_idxty_tycon ++ implicit_things) $ do {
+
+               -- (3) Instances from generic class declarations
        ; generic_inst_info <- getGenericInstances clas_decls
 
                -- Next, construct the instance environment so far, consisting
                -- of 
                --   a) local instance decls
                --   b) generic instances
-       ; addInsts local_inst_info   $ do {
+       ; addInsts local_idxty_info  $ do {
        ; addInsts generic_inst_info $ do {
 
-               -- (3) Compute instances from "deriving" clauses; 
+               -- (4) Compute instances from "deriving" clauses; 
                -- This stuff computes a context for the derived instance
                -- decl, so it needs to know about all the instances possible
        ; (deriv_inst_info, deriv_binds) <- tcDeriving tycl_decls
@@ -171,9 +185,30 @@ tcInstDecls1 tycl_decls inst_decls
 
        ; gbl_env <- getGblEnv
        ; returnM (gbl_env, 
-                 generic_inst_info ++ deriv_inst_info ++ local_inst_info,
+                 generic_inst_info ++ deriv_inst_info ++ local_idxty_info,
                  deriv_binds) 
-    }}}}
+    }}}}}
+  where
+    -- Make sure that toplevel type instance are not for associated types.
+    -- !!!TODO: Need to perform this check for the InstInfo structures of type
+    --         functions, too.
+    tcIdxTyInstDeclTL ldecl@(L loc decl) =
+      do { (info, tything) <- tcIdxTyInstDecl ldecl
+        ; setSrcSpan loc $
+            when (isAssocFamily tything) $
+              addErr $ assocInClassErr (tcdName decl)
+        ; return (info, tything)
+        }
+    isAssocFamily (Just (ATyCon tycon)) =
+      case tyConFamInst_maybe tycon of
+        Nothing       -> panic "isAssocFamily: no family?!?"
+       Just (fam, _) -> isAssocTyCon fam
+    isAssocFamily (Just _            ) = panic "isAssocFamily: no tycon?!?"
+    isAssocFamily Nothing               = False
+
+assocInClassErr name = 
+  ptext SLIT("Associated type must be inside class instance") <+> 
+  quotes (ppr name)
 
 addInsts :: [InstInfo] -> TcM a -> TcM a
 addInsts infos thing_inside
@@ -182,14 +217,14 @@ addInsts infos thing_inside
 
 \begin{code}
 tcLocalInstDecl1 :: LInstDecl Name 
-                -> TcM [InstInfo]      -- [] if there was an error
+                -> TcM ([InstInfo], [TyThing]) -- [] if there was an error
        -- A source-file instance declaration
        -- Type-check all the stuff before the "where"
        --
        -- We check for respectable instance type, and context
 tcLocalInstDecl1 decl@(L loc (InstDecl poly_ty binds uprags ats))
   =    -- Prime error recovery, set source location
-    recoverM (returnM [])              $
+    recoverM (returnM ([], []))                $
     setSrcSpan loc                     $
     addErrCtxt (instDeclCtxt1 poly_ty) $
 
@@ -208,18 +243,22 @@ tcLocalInstDecl1 decl@(L loc (InstDecl poly_ty binds uprags ats))
        ; checkValidInstance tyvars theta clas inst_tys
 
        -- Next, process any associated types.
-       ; idxty_inst_info <- mappM tcIdxTyInstDecl ats
+       ; idxty_info_tycons <- mappM tcIdxTyInstDecl ats
 
        -- Finally, construct the Core representation of the instance.
        -- (This no longer includes the associated types.)
        ; dfun_name <- newDFunName clas inst_tys (srcSpanStart loc)
        ; overlap_flag <- getOverlapFlag
-       ; let dfun  = mkDictFunId dfun_name tyvars theta clas inst_tys
-             ispec = mkLocalInstance dfun overlap_flag
-
-       ; return $ [InstInfo { iSpec  = ispec, 
-                              iBinds = VanillaInst binds uprags }] ++
-                   catMaybes idxty_inst_info }
+       ; let dfun           = mkDictFunId dfun_name tyvars theta clas inst_tys
+             ispec          = mkLocalInstance dfun overlap_flag
+             (idxty_infos, 
+              idxty_tycons) = unzip idxty_info_tycons
+
+       ; return ([InstInfo { iSpec  = ispec, 
+                             iBinds = VanillaInst binds uprags }] ++
+                  catMaybes idxty_infos,
+                 catMaybes idxty_tycons)
+        }
 \end{code}