Store a SrcSpan instead of a SrcLoc inside a Name
[ghc-hetmet.git] / compiler / typecheck / TcDeriv.lhs
index de0f133..98d7fcf 100644 (file)
@@ -381,6 +381,8 @@ deriveTyData (deriv_pred, L loc decl@(TyData { tcdLName = L _ tycon_name,
                -- The "deriv_pred" is a LHsType to take account of the fact that for
                -- newtype deriving we allow deriving (forall a. C [a]).
        ; mkEqnHelp DerivOrigin (tvs++deriv_tvs) cls cls_tys tc_app } }
+deriveTyData (deriv_pred, other_decl)
+  = panic "derivTyData"        -- Caller ensures that only TyData can happen
 
 ------------------------------------------------------------------
 mkEqnHelp orig tvs cls cls_tys tc_app
@@ -419,7 +421,8 @@ baleOut err = addErrTc err >> returnM (Nothing, Nothing)
 
 \begin{code}
 mkDataTypeEqn orig gla_exts tvs cls cls_tys tycon tc_args rep_tc rep_tc_args
-  | Just err <- checkSideConditions gla_exts cls cls_tys tycon tc_args
+  | Just err <- checkSideConditions gla_exts cls cls_tys rep_tc
+       -- NB: pass the *representation* tycon to checkSideConditions
   = baleOut (derivingThingErr cls cls_tys (mkTyConApp tycon tc_args) err)
 
   | otherwise 
@@ -464,15 +467,19 @@ mk_data_eqn loc orig tvs cls tycon tc_args rep_tc rep_tc_args
 ------------------------------------------------------------------
 -- Check side conditions that dis-allow derivability for particular classes
 -- This is *apart* from the newtype-deriving mechanism
+--
+-- Here we get the representation tycon in case of family instances as it has
+-- the data constructors - but we need to be careful to fall back to the
+-- family tycon (with indexes) in error messages.
 
-checkSideConditions :: Bool -> Class -> [TcType] -> TyCon -> [TcType] -> Maybe SDoc
-checkSideConditions gla_exts cls cls_tys tycon tc_tys
+checkSideConditions :: Bool -> Class -> [TcType] -> TyCon -> Maybe SDoc
+checkSideConditions gla_exts cls cls_tys rep_tc
   | notNull cls_tys    
   = Just ty_args_why   -- e.g. deriving( Foo s )
   | otherwise
   = case [cond | (key,cond) <- sideConditions, key == getUnique cls] of
        []     -> Just (non_std_why cls)
-       [cond] -> cond (gla_exts, tycon)
+       [cond] -> cond (gla_exts, rep_tc)
        other  -> pprPanic "checkSideConditions" (ppr cls)
   where
     ty_args_why        = quotes (ppr (mkClassPred cls cls_tys)) <+> ptext SLIT("is not a class")
@@ -492,7 +499,11 @@ sideConditions
        (dataClassKey,     cond_glaExts `andCond` cond_std)
     ]
 
-type Condition = (Bool, TyCon) -> Maybe SDoc   -- Nothing => OK
+type Condition = (Bool, TyCon) -> Maybe SDoc
+       -- Bool is gla-exts flag
+       -- TyCon is the *representation* tycon if the 
+       --      data type is an indexed one
+       -- Nothing => OK
 
 orCond :: Condition -> Condition -> Condition
 orCond c1 c2 tc 
@@ -508,66 +519,66 @@ andCond c1 c2 tc = case c1 tc of
                     Just x  -> Just x  -- c1 fails
 
 cond_std :: Condition
-cond_std (gla_exts, tycon)
+cond_std (gla_exts, rep_tc)
   | any (not . isVanillaDataCon) data_cons = Just existential_why     
   | null data_cons                        = Just no_cons_why
   | otherwise                             = Nothing
   where
-    data_cons       = tyConDataCons tycon
-    no_cons_why            = quotes (ppr tycon) <+> ptext SLIT("has no data constructors")
-    existential_why = quotes (ppr tycon) <+> ptext SLIT("has non-Haskell-98 constructor(s)")
+    data_cons       = tyConDataCons rep_tc
+    no_cons_why            = quotes (pprSourceTyCon rep_tc) <+> 
+                     ptext SLIT("has no data constructors")
+    existential_why = quotes (pprSourceTyCon rep_tc) <+> 
+                     ptext SLIT("has non-Haskell-98 constructor(s)")
   
 cond_isEnumeration :: Condition
-cond_isEnumeration (gla_exts, tycon)
-  | isEnumerationTyCon tycon = Nothing
-  | otherwise               = Just why
+cond_isEnumeration (gla_exts, rep_tc)
+  | isEnumerationTyCon rep_tc = Nothing
+  | otherwise                = Just why
   where
-    why = quotes (ppr tycon) <+> ptext SLIT("has non-nullary constructors")
+    why = quotes (pprSourceTyCon rep_tc) <+> 
+         ptext SLIT("has non-nullary constructors")
 
 cond_isProduct :: Condition
-cond_isProduct (gla_exts, tycon)
-  | isProductTyCon tycon = Nothing
-  | otherwise           = Just why
+cond_isProduct (gla_exts, rep_tc)
+  | isProductTyCon rep_tc = Nothing
+  | otherwise            = Just why
   where
-    why = quotes (ppr tycon) <+> ptext SLIT("has more than one constructor")
+    why = quotes (pprSourceTyCon rep_tc) <+> 
+         ptext SLIT("has more than one constructor")
 
 cond_typeableOK :: Condition
 -- OK for Typeable class
 -- Currently: (a) args all of kind *
 --           (b) 7 or fewer args
-cond_typeableOK (gla_exts, tycon)
-  | tyConArity tycon > 7       = Just too_many
-  | not (all (isSubArgTypeKind . tyVarKind) (tyConTyVars tycon)) 
+cond_typeableOK (gla_exts, rep_tc)
+  | tyConArity rep_tc > 7      = Just too_many
+  | not (all (isSubArgTypeKind . tyVarKind) (tyConTyVars rep_tc)) 
                                 = Just bad_kind
-  | isFamInstTyCon tycon       = Just fam_inst  -- no Typable for family insts
+  | isFamInstTyCon rep_tc      = Just fam_inst  -- no Typable for family insts
   | otherwise                  = Nothing
   where
-    too_many = quotes (ppr tycon) <+> ptext SLIT("has too many arguments")
-    bad_kind = quotes (ppr tycon) <+> 
+    too_many = quotes (pprSourceTyCon rep_tc) <+> 
+              ptext SLIT("has too many arguments")
+    bad_kind = quotes (pprSourceTyCon rep_tc) <+> 
               ptext SLIT("has arguments of kind other than `*'")
-    fam_inst = quotes (ppr tycon) <+> ptext SLIT("is a type family")
+    fam_inst = quotes (pprSourceTyCon rep_tc) <+> 
+              ptext SLIT("is a type family")
 
 cond_glaExts :: Condition
-cond_glaExts (gla_exts, tycon) | gla_exts  = Nothing
-                              | otherwise = Just why
+cond_glaExts (gla_exts, _rep_tc) | gla_exts  = Nothing
+                                | otherwise = Just why
   where
     why  = ptext SLIT("You need -fglasgow-exts to derive an instance for this class")
 
-std_class gla_exts clas 
-  =  key `elem` derivableClassKeys
-  || (gla_exts && (key == typeableClassKey || key == dataClassKey))
-  where
-     key = classKey clas
-    
 std_class_via_iso clas -- These standard classes can be derived for a newtype
                        -- using the isomorphism trick *even if no -fglasgow-exts*
   = classKey clas `elem`  [eqClassKey, ordClassKey, ixClassKey, boundedClassKey]
        -- Not Read/Show because they respect the type
-       -- Not Enum, becuase newtypes are never in Enum
+       -- Not Enum, because newtypes are never in Enum
 
 
 new_dfun_name clas tycon       -- Just a simple wrapper
-  = newDFunName clas [mkTyConApp tycon []] (getSrcLoc tycon)
+  = newDFunName clas [mkTyConApp tycon []] (getSrcSpan tycon)
        -- The type passed to newDFunName is only used to generate
        -- a suitable string; hence the empty type arg list
 \end{code}
@@ -584,18 +595,26 @@ mkNewTypeEqn orig gla_exts overlap_flag tvs cls cls_tys
             tycon tc_args 
             rep_tycon rep_tc_args
   | can_derive_via_isomorphism && (gla_exts || std_class_via_iso cls)
-  =    do { traceTc (text "newtype deriving:" <+> ppr tycon <+> ppr rep_tys)
-          ;    -- Go ahead and use the isomorphism
-            dfun_name <- new_dfun_name cls tycon
-          ; return (Nothing, Just (InstInfo { iSpec  = mk_inst_spec dfun_name,
-                                              iBinds = NewTypeDerived ntd_info })) }
-  | std_class gla_exts cls
-  = mkDataTypeEqn orig gla_exts tvs cls cls_tys tycon tc_args rep_tycon rep_tc_args    -- Go via bale-out route
-
-       -- Otherwise its a non-standard instance
+  = do { traceTc (text "newtype deriving:" <+> ppr tycon <+> ppr rep_tys)
+       ;       -- Go ahead and use the isomorphism
+          dfun_name <- new_dfun_name cls tycon
+       ; return (Nothing, Just (InstInfo { iSpec  = mk_inst_spec dfun_name,
+                                           iBinds = NewTypeDerived ntd_info })) }
+
+  | isNothing mb_std_err       -- Use the standard H98 method
+  = do { loc <- getSrcSpanM
+       ; eqn <- mk_data_eqn loc orig tvs cls tycon tc_args rep_tycon rep_tc_args
+       ; return (Just eqn, Nothing) }
+
+       -- Otherwise we can't derive
   | gla_exts  = baleOut cant_derive_err        -- Too hard
-  | otherwise = baleOut non_std_err    -- Just complain about being a non-std instance
+  | otherwise = baleOut std_err                -- Just complain about being a non-std instance
   where
+       mb_std_err = checkSideConditions gla_exts cls cls_tys rep_tycon
+       std_err = derivingThingErr cls cls_tys tc_app $
+                 vcat [fromJust mb_std_err,
+                       ptext SLIT("Try -fglasgow-exts for GHC's newtype-deriving extension")]
+
        -- Here is the plan for newtype derivings.  We see
        --        newtype T a1...an = MkT (t ak+1...an) deriving (.., C s1 .. sm, ...)
        -- where t is a type,
@@ -737,7 +756,7 @@ mkNewTypeEqn orig gla_exts overlap_flag tvs cls cls_tys
        cant_derive_err = derivingThingErr cls cls_tys tc_app
                                (vcat [ptext SLIT("even with cunning newtype deriving:"),
                                        if isRecursiveTyCon tycon then
-                                         ptext SLIT("the newtype is recursive")
+                                         ptext SLIT("the newtype may be recursive")
                                        else empty,
                                        if not right_arity then 
                                          quotes (ppr (mkClassPred cls cls_tys)) <+> ptext SLIT("does not have arity 1")
@@ -750,10 +769,6 @@ mkNewTypeEqn orig gla_exts overlap_flag tvs cls cls_tys
                                          ptext SLIT("the eta-reduction property does not hold")
                                        else empty
                                      ])
-
-       non_std_err = derivingThingErr cls cls_tys tc_app
-                               (vcat [non_std_why cls,
-                                      ptext SLIT("Try -fglasgow-exts for GHC's newtype-deriving extension")])
 \end{code}
 
 
@@ -862,6 +877,26 @@ extendLocalInstEnv dfuns thing_inside
       ; setGblEnv env' thing_inside }
 \end{code}
 
+Note [Deriving context]
+~~~~~~~~~~~~~~~~~~~~~~~
+With -fglasgow-exts, we allow things like (C Int a) in the simplified
+context for a derived instance declaration, because at a use of this
+instance, we might know that a=Bool, and have an instance for (C Int
+Bool)
+
+We nevertheless insist that each predicate meets the termination
+conditions. If not, the deriving mechanism generates larger and larger
+constraints.  Example:
+  data Succ a = S a
+  data Seq a = Cons a (Seq (Succ a)) | Nil deriving Show
+
+Note the lack of a Show instance for Succ.  First we'll generate
+  instance (Show (Succ a), Show a) => Show (Seq a)
+and then
+  instance (Show (Succ (Succ a)), Show (Succ a), Show a) => Show (Seq a)
+and so on.  Instead we want to complain of no instance for (Show (Succ a)).
+  
+
 %************************************************************************
 %*                                                                     *
 \subsection[TcDeriv-normal-binds]{Bindings for the various classes}
@@ -1087,3 +1122,4 @@ badDerivedPred pred
          nest 2 (ptext SLIT("Offending constraint:") <+> ppr pred)]
 \end{code}