-- doesn't have to be when reading interface files
 
 data HsType name
-  = HsForAllTy         [HsTyVar name]
+  = HsForAllTy         (Maybe [HsTyVar name])  -- Nothing for implicitly quantified signatures
                        (Context name)
                        (HsType name)
 
                        [HsType name]
 
 mkHsForAllTy []  []   ty = ty
-mkHsForAllTy tvs ctxt ty = HsForAllTy tvs ctxt ty
+mkHsForAllTy tvs ctxt ty = HsForAllTy (Just tvs) ctxt ty
 
 data HsTyVar name
   = UserTyVar name
 pprHsType ty       = ppr_mono_ty pREC_TOP ty
 pprParendHsType ty = ppr_mono_ty pREC_CON ty
 
-ppr_mono_ty ctxt_prec (HsForAllTy tvs ctxt ty)
+ppr_mono_ty ctxt_prec (HsForAllTy maybe_tvs ctxt ty)
   = maybeParen (ctxt_prec >= pREC_FUN) $
     sep [pprForAll tvs, pprContext ctxt, pprHsType ty]
+  where
+    tvs = case maybe_tvs of
+               Just tvs -> tvs
+               Nothing  -> []
 
 ppr_mono_ty ctxt_prec (MonoTyVar name)
   = ppr name
 cmpHsTypes cmp (ty1:tys1) (ty2:tys2) = cmpHsType cmp ty1 ty2 `thenCmp` cmpHsTypes cmp tys1 tys2
 
 cmpHsType cmp (HsForAllTy tvs1 c1 t1) (HsForAllTy tvs2 c2 t2)
-  = cmpList (cmpHsTyVar cmp) tvs1 tvs2  `thenCmp`
-    cmpContext cmp c1 c2               `thenCmp`
+  = cmpMaybe (cmpList (cmpHsTyVar cmp)) tvs1 tvs2      `thenCmp`
+    cmpContext cmp c1 c2                               `thenCmp`
     cmpHsType cmp t1 t2
 
 cmpHsType cmp (MonoTyVar n1) (MonoTyVar n2)
   where
     cmp_ctxt (c1, tys1) (c2, tys2)
       = cmp c1 c2 `thenCmp` cmpHsTypes cmp tys1 tys2
+
+-- Should be in Maybes, I guess
+cmpMaybe cmp Nothing  Nothing  = EQ
+cmpMaybe cmp Nothing  (Just x) = LT
+cmpMaybe cmp (Just x)  Nothing = GT
+cmpMaybe cmp (Just x) (Just y) = x `cmp` y
 \end{code}
 
        -- make sure it starts with a ForAll
     case ty of
        HsForAllTy _ _ _ -> returnUgn ty
-       other            -> returnUgn (HsForAllTy [] [] ty)
+       other            -> returnUgn (HsForAllTy Nothing [] ty)
 
 wlkHsType :: U_ttype -> UgnM RdrNameHsType
 wlkHsType ttype
   = case ttype of
-      U_forall u_tyvars u_theta u_ty -> -- context
+      U_forall u_tyvars u_theta u_ty -> -- Explicit forall
        wlkList rdTvId u_tyvars         `thenUgn` \ tyvars -> 
        wlkContext u_theta              `thenUgn` \ theta ->
        wlkHsType u_ty                  `thenUgn` \ ty   ->
-       returnUgn (HsForAllTy (map UserTyVar tyvars) theta ty)
+       returnUgn (HsForAllTy (Just (map UserTyVar tyvars)) theta ty)
+
+      U_imp_forall u_theta u_ty ->     -- Implicit forall
+       wlkContext u_theta              `thenUgn` \ theta ->
+       wlkHsType u_ty                  `thenUgn` \ ty   ->
+       returnUgn (HsForAllTy Nothing theta ty)
 
       U_namedtvar tv -> -- type variable
        wlkTvId tv      `thenUgn` \ tyvar ->
        wlkList rdTvId u_tyvars         `thenUgn` \ tyvars -> 
        wlkContext  u_theta             `thenUgn` \ theta ->
        wlkClsTys inst_head             `thenUgn` \ (clas, tys)  ->
-       returnUgn (HsForAllTy (map UserTyVar tyvars) theta (MonoDictTy clas tys))
+       returnUgn (HsForAllTy (Just (map UserTyVar tyvars)) theta (MonoDictTy clas tys))
+
+      U_imp_forall u_theta inst_head ->
+       wlkContext  u_theta             `thenUgn` \ theta ->
+       wlkClsTys inst_head             `thenUgn` \ (clas, tys)  ->
+       returnUgn (HsForAllTy Nothing theta (MonoDictTy clas tys))
 
       other -> -- something else
        wlkClsTys other   `thenUgn` \ (clas, tys) ->
-       returnUgn (HsForAllTy [] [] (MonoDictTy clas tys))
+       returnUgn (HsForAllTy Nothing [] (MonoDictTy clas tys))
 \end{code}
 
 \begin{code}
 
 import Outputable
 import SrcLoc          ( SrcLoc )
 import UniqFM          ( lookupUFM )
-import Maybes          ( maybeToBool )
+import Maybes          ( maybeToBool, catMaybes )
 import Util
 \end{code}
 
     rnHsSigType (text "an instance decl") inst_ty      `thenRn` \ (inst_ty', inst_fvs) ->
     let
        inst_tyvars = case inst_ty' of
-                       HsForAllTy inst_tyvars _ _ -> inst_tyvars
-                       other                      -> []
+                       HsForAllTy (Just inst_tyvars) _ _ -> inst_tyvars
+                       other                             -> []
        -- (Slightly strangely) the forall-d tyvars scope over
        -- the method bindings too
     in
  = rnHsType doc ty     `thenRn` \ (ty,_) ->
    returnRn ty
 
+
+rnForAll doc forall_tyvars ctxt ty
+  = bindTyVarsFVRn doc forall_tyvars                   $ \ new_tyvars ->
+    rnContext doc ctxt                                 `thenRn` \ (new_ctxt, cxt_fvs) ->
+    rnHsType doc ty                                    `thenRn` \ (new_ty, ty_fvs) ->
+    returnRn (mkHsForAllTy new_tyvars new_ctxt new_ty,
+             cxt_fvs `plusFV` ty_fvs)
+
+-- Check that each constraint mentions at least one of the forall'd type variables
+-- Since the forall'd type variables are a subset of the free tyvars
+-- of the tau-type part, this guarantees that every constraint mentions
+-- at least one of the free tyvars in ty
+checkConstraints explicit_forall doc forall_tyvars ctxt ty
+   = mapRn check ctxt                  `thenRn` \ maybe_ctxt' ->
+     returnRn (catMaybes maybe_ctxt')
+           -- Remove problem ones, to avoid duplicate error message.
+   where
+     check ct@(_,tys)
+       | forall_mentioned = returnRn (Just ct)
+       | otherwise        = addErrRn (ctxtErr explicit_forall doc forall_tyvars ct ty) `thenRn_`
+                            returnRn Nothing
+        where
+         forall_mentioned = foldr ((||) . any (`elem` forall_tyvars) . extractHsTyVars)
+                            False
+                            tys
+
+
 rnHsType :: SDoc -> RdrNameHsType -> RnMS s (RenamedHsType, FreeVars)
 
-rnHsType doc (HsForAllTy [] ctxt ty)
+rnHsType doc (HsForAllTy Nothing ctxt ty)
        -- From source code (no kinds on tyvars)
-
        -- Given the signature  C => T  we universally quantify 
        -- over FV(T) \ {in-scope-tyvars} 
-       -- 
-       -- We insist that the universally quantified type vars is a superset of FV(C)
-       -- It follows that FV(T) is a superset of FV(C), so that the context constrains
-       -- no type variables that don't appear free in the tau-type part.
-
   = getLocalNameEnv            `thenRn` \ name_env ->
     let
        mentioned_tyvars = extractHsTyVars ty
        forall_tyvars    = filter (not . (`elemFM` name_env)) mentioned_tyvars
-
-       ctxt_w_ftvs :: [((RdrName,[RdrNameHsType]), [RdrName])]
-       ctxt_w_ftvs  = [ (constraint, foldr ((++) . extractHsTyVars) [] tys)
-                      | constraint@(_,tys) <- ctxt]
-
-       -- A 'non-poly constraint' is one that does not mention *any*
-       -- of the forall'd type variables
-       non_poly_constraints = filter non_poly ctxt_w_ftvs
-       non_poly (c,ftvs)    = not (any (`elem` forall_tyvars) ftvs)
-
-       -- A 'non-mentioned' constraint is one that mentions a
-       -- type variable that does not appear in 'ty'
-       non_mentioned_constraints = filter non_mentioned ctxt_w_ftvs
-       non_mentioned (c,ftvs)    = any (not . (`elem` mentioned_tyvars)) ftvs
-
-       -- Zap the context if there's a problem, to avoid duplicate error message.
-       ctxt' | null non_poly_constraints && null non_mentioned_constraints = ctxt
-             | otherwise = []
     in
-    mapRn (ctxtErr1 doc forall_tyvars ty) non_poly_constraints         `thenRn_`
-    mapRn (ctxtErr2 doc ty)               non_mentioned_constraints    `thenRn_`
-
-    (bindTyVarsFVRn doc (map UserTyVar forall_tyvars)  $ \ new_tyvars ->
-    rnContext doc ctxt'                                        `thenRn` \ (new_ctxt, cxt_fvs) ->
-    rnHsType doc ty                                    `thenRn` \ (new_ty, ty_fvs) ->
-    returnRn (mkHsForAllTy new_tyvars new_ctxt new_ty,
-             cxt_fvs `plusFV` ty_fvs)
-    )
-
-rnHsType doc (HsForAllTy tvs ctxt ty)
-       -- tvs are non-empty, hence must be from an interface file
-       --      (tyvars may be kinded)
-  = bindTyVarsFVRn doc tvs             $ \ new_tyvars ->
-    rnContext doc ctxt                 `thenRn` \ (new_ctxt, cxt_fvs) ->
-    rnHsType doc ty                    `thenRn` \ (new_ty, ty_fvs) ->
-    returnRn (mkHsForAllTy new_tyvars new_ctxt new_ty,
-             cxt_fvs `plusFV` ty_fvs)
+    checkConstraints False doc forall_tyvars ctxt ty   `thenRn` \ ctxt' ->
+    rnForAll doc (map UserTyVar forall_tyvars) ctxt' ty
+
+rnHsType doc (HsForAllTy (Just forall_tyvars) ctxt ty)
+       -- Explicit quantification.
+       -- Check that the forall'd tyvars are a subset of the
+       -- free tyvars in the tau-type part
+  = let
+       mentioned_tyvars   = extractHsTyVars ty
+       bad_guys           = filter (`notElem` mentioned_tyvars) forall_tyvar_names
+       forall_tyvar_names = map getTyVarName forall_tyvars
+    in
+    mapRn (forAllErr doc ty) bad_guys                          `thenRn_`
+    checkConstraints True doc forall_tyvar_names ctxt ty       `thenRn` \ ctxt' ->
+    rnForAll doc forall_tyvars ctxt' ty
 
 rnHsType doc (MonoTyVar tyvar)
   = lookupOccRn tyvar          `thenRn` \ tyvar' ->
 badDataCon name
    = hsep [ptext SLIT("Illegal data constructor name"), quotes (ppr name)]
 
-ctxtErr1 doc tyvars ty (constraint, _)
+forAllErr doc ty tyvar
   = addErrRn (
-      sep [ptext SLIT("The constraint") <+> quotes (pprClassAssertion constraint) <+>
-                  ptext SLIT("does not mention any of"),
-          nest 4 (ptext SLIT("the universally quantified type variables") <+> braces (interpp'SP tyvars)),
-          nest 4 (ptext SLIT("of the type") <+> quotes (ppr ty))
-      ]
+      sep [ptext SLIT("The universally quantified type variable") <+> quotes (ppr tyvar),
+          nest 4 (ptext SLIT("does not appear in the type") <+> quotes (ppr ty))]
       $$
-      (ptext SLIT("In") <+> doc)
-    )
+      (ptext SLIT("In") <+> doc))
 
-ctxtErr2 doc ty (constraint,_)
-  = addErrRn (
-       sep [ptext SLIT("The constraint") <+> quotes (pprClassAssertion constraint),
-       nest 4 (ptext SLIT("mentions type variables that do not appear in the type")),
-       nest 4 (quotes (ppr ty))]
-        $$
-       (ptext SLIT("In") <+> doc)
-    )
+ctxtErr explicit_forall doc tyvars constraint ty
+  = sep [ptext SLIT("The constraint") <+> quotes (pprClassAssertion constraint) <+>
+                  ptext SLIT("does not mention any of"),
+        if explicit_forall then
+          nest 4 (ptext SLIT("the universally quantified type variables") <+> braces (interpp'SP tyvars))
+        else
+          nest 4 (ptext SLIT("the type variables in the type") <+> quotes (ppr ty))
+    ]
+    $$
+    (ptext SLIT("In") <+> doc)
 \end{code}