Tidy up treatment of FlexibleContexts
authorSimon Peyton Jones <simonpj@microsoft.com>
Thu, 30 Apr 2015 08:18:49 +0000 (09:18 +0100)
committerSimon Peyton Jones <simonpj@microsoft.com>
Thu, 30 Apr 2015 08:22:20 +0000 (09:22 +0100)
Previously (Trac #10351) we could get

    Non type-variable argument in the constraint: C [t]
    (Use FlexibleContexts to permit this)
    When checking that `f' has the inferred type
      f :: forall t. C [t] => t -> ()

which is a bit stupid: we have *inferred* a type that we
immediately *reject*.  This patch arranges that that the
generalisation mechanism (TcSimplify.decideQuantification)
doesn't pick a predicate that will be rejected by the
subsequent validity check.

This forced some minor refactoring, as usual.

compiler/main/DynFlags.hs
compiler/typecheck/TcBinds.hs
compiler/typecheck/TcSimplify.hs
compiler/typecheck/TcType.hs
compiler/typecheck/TcValidity.hs
testsuite/tests/typecheck/should_fail/T10351.hs [new file with mode: 0644]
testsuite/tests/typecheck/should_fail/T10351.stderr [new file with mode: 0644]
testsuite/tests/typecheck/should_fail/T6022.stderr
testsuite/tests/typecheck/should_fail/T8883.stderr
testsuite/tests/typecheck/should_fail/all.T
testsuite/tests/typecheck/should_fail/tcfail108.stderr

index 094984b..f078c51 100644 (file)
@@ -3264,11 +3264,6 @@ impliedXFlags
 
     , (Opt_ParallelArrays, turnOn, Opt_ParallelListComp)
 
-    -- An implicit parameter constraint, `?x::Int`, is desugared into
-    -- `IP "x" Int`, which requires a flexible context/instance.
-    , (Opt_ImplicitParams, turnOn, Opt_FlexibleContexts)
-    , (Opt_ImplicitParams, turnOn, Opt_FlexibleInstances)
-
     , (Opt_JavaScriptFFI, turnOn, Opt_InterruptibleFFI)
 
     , (Opt_DeriveTraversable, turnOn, Opt_DeriveFunctor)
index 17f6078..64333eb 100644 (file)
@@ -688,8 +688,9 @@ mkInferredPolyId poly_name qtvs theta mono_ty
              my_tvs2 = closeOverKinds (growThetaTyVars theta (tyVarsOfType norm_mono_ty))
                   -- Include kind variables!  Trac #7916
 
-             my_tvs   = filter (`elemVarSet` my_tvs2) qtvs   -- Maintain original order
-             my_theta = filter (quantifyPred my_tvs2) theta
+       ; my_theta <- pickQuantifiablePreds my_tvs2 theta
+
+       ; let my_tvs   = filter (`elemVarSet` my_tvs2) qtvs   -- Maintain original order
              inferred_poly_ty = mkSigmaTy my_tvs my_theta norm_mono_ty
 
        ; addErrCtxtM (mk_bind_msg True False poly_name inferred_poly_ty) $
index 5f9f417..c1535f8 100644 (file)
@@ -2,7 +2,7 @@
 
 module TcSimplify(
        simplifyInfer,
-       quantifyPred, growThetaTyVars,
+       pickQuantifiablePreds, growThetaTyVars,
        simplifyAmbiguityCheck,
        simplifyDefault,
        simplifyTop, simplifyInteractive,
@@ -40,7 +40,7 @@ import Util
 import PrelInfo
 import PrelNames
 import Control.Monad    ( unless )
-import DynFlags         ( ExtensionFlag( Opt_AllowAmbiguousTypes ) )
+import DynFlags         ( ExtensionFlag( Opt_AllowAmbiguousTypes, Opt_FlexibleContexts ) )
 import Class            ( classKey )
 import Maybes           ( isNothing )
 import Outputable
@@ -424,8 +424,9 @@ If the monomorphism restriction does not apply, then we quantify as follows:
     (This actually unifies each quantifies meta-tyvar with a fresh skolem.)
     Result is qtvs.
 
-  * Filter the constraints using quantifyPred and the qtvs.  We have to
-    zonk the constraints first, so they "see" the freshly created skolems.
+  * Filter the constraints using pickQuantifyablePreds and the qtvs.
+    We have to zonk the constraints first, so they "see" the freshly
+    created skolems.
 
 If the MR does apply, mono_tvs includes all the constrained tyvars,
 and the quantified constraints are empty.
@@ -457,31 +458,43 @@ decideQuantification apply_mr constraints zonked_tau_tvs
               -- quantifyTyVars turned some meta tyvars into
               -- quantified skolems, so we have to zonk again
 
-       ; let theta     = filter (quantifyPred (mkVarSet qtvs)) constraints
-             min_theta = mkMinimalBySCs theta  -- See Note [Minimize by Superclasses]
+       ; theta <- pickQuantifiablePreds (mkVarSet qtvs) constraints
+       ; let min_theta = mkMinimalBySCs theta  -- See Note [Minimize by Superclasses]
+
        ; traceTc "decideQuantification 2" (vcat [ppr constraints, ppr gbl_tvs, ppr mono_tvs
                                                 , ppr tau_tvs_plus, ppr qtvs, ppr min_theta])
        ; return (qtvs, min_theta, False) }
 
 ------------------
-quantifyPred :: TyVarSet           -- Quantifying over these
-             -> PredType -> Bool   -- True <=> quantify over this wanted
+pickQuantifiablePreds :: TyVarSet         -- Quantifying over these
+                      -> TcThetaType      -- Proposed constraints to quantify
+                      -> TcM TcThetaType  -- A subset that we can actually quantify
 -- This function decides whether a particular constraint shoudl be
 -- quantified over, given the type variables that are being quantified
-quantifyPred qtvs pred
-  = case classifyPredType pred of
-      ClassPred cls tys
-         | isIPClass cls    -> True -- See note [Inheriting implicit parameters]
-         | otherwise        -> tyVarsOfTypes tys `intersectsVarSet` qtvs
-
-      EqPred NomEq ty1 ty2  -> quant_fun ty1 || quant_fun ty2
-        -- representational equality is like a class constraint
-      EqPred ReprEq ty1 ty2 -> tyVarsOfTypes [ty1, ty2] `intersectsVarSet` qtvs
-
-      IrredPred ty          -> tyVarsOfType ty `intersectsVarSet` qtvs
-      TuplePred {}          -> False
+pickQuantifiablePreds qtvs theta
+  = do { flex_ctxt <- xoptM Opt_FlexibleContexts
+       ; return (filter (pick_me flex_ctxt) theta) }
   where
-    -- See Note [Quantifying over equality constraints]
+    pick_me flex_ctxt pred
+      = case classifyPredType pred of
+          ClassPred cls tys
+             | isIPClass cls -> True -- See note [Inheriting implicit parameters]
+             | otherwise     -> pick_cls_pred flex_ctxt tys
+
+          EqPred ReprEq ty1 ty2 -> pick_cls_pred flex_ctxt [ty1, ty2]
+                -- Representational equality is like a class constraint
+
+          EqPred NomEq ty1 ty2  -> quant_fun ty1 || quant_fun ty2
+          IrredPred ty          -> tyVarsOfType ty `intersectsVarSet` qtvs
+          TuplePred {}          -> False
+
+    pick_cls_pred flex_ctxt tys
+      = tyVarsOfTypes tys `intersectsVarSet` qtvs
+        && (checkValidClsArgs flex_ctxt tys)
+           -- Only quantify over predicates that checkValidType
+           -- will pass!  See Trac #10351.
+
+        -- See Note [Quantifying over equality constraints]
     quant_fun ty
       = case tcSplitTyConApp_maybe ty of
           Just (tc, tys) | isTypeFamilyTyCon tc
@@ -558,7 +571,7 @@ dynamic binding means) so we'd better infer the second.
 BOTTOM LINE: when *inferring types* you must quantify over implicit
 parameters, *even if* they don't mention the bound type variables.
 Reason: because implicit parameters, uniquely, have local instance
-declarations. See the predicate quantifyPred.
+declarations. See the pickQuantifiablePreds.
 
 Note [Quantification with errors]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
index 4185be8..4d4f682 100644 (file)
@@ -69,6 +69,7 @@ module TcType (
   isIntegerTy, isBoolTy, isUnitTy, isCharTy,
   isTauTy, isTauTyCon, tcIsTyVarTy, tcIsForAllTy,
   isPredTy, isTyVarClassPred, isTyVarExposed,
+  checkValidClsArgs, hasTyVarHead,
 
   ---------------------------------
   -- Misc type manipulators
@@ -1313,6 +1314,14 @@ straightforward.
 ************************************************************************
 
 Deconstructors and tests on predicate types
+
+Note [Kind polymorphic type classes]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    class C f where...   -- C :: forall k. k -> Constraint
+    g :: forall (f::*). C f => f -> f
+
+Here the (C f) in the signature is really (C * f), and we 
+don't want to complain that the * isn't a type variable!
 -}
 
 isTyVarClassPred :: PredType -> Bool
@@ -1320,6 +1329,28 @@ isTyVarClassPred ty = case getClassPredTys_maybe ty of
     Just (_, tys) -> all isTyVarTy tys
     _             -> False
 
+-------------------------
+checkValidClsArgs :: Bool -> [KindOrType] -> Bool
+-- If the Bool is True (flexible contexts), return True (i.e. ok)
+-- Otherwise, check that the type (not kind) args are all headed by a tyvar
+--   E.g. (Eq a) accepted, (Eq (f a)) accepted, but (Eq Int) rejected
+-- This function is here rather than in TcValidity because it is
+-- called from TcSimplify, which itself is imported by TcValidity
+checkValidClsArgs flexible_contexts kts
+  | flexible_contexts = True
+  | otherwise         = all hasTyVarHead tys
+  where
+    (_, tys) = span isKind kts  -- see Note [Kind polymorphic type classes]
+   
+hasTyVarHead :: Type -> Bool
+-- Returns true of (a t1 .. tn), where 'a' is a type variable
+hasTyVarHead ty                 -- Haskell 98 allows predicates of form
+  | tcIsTyVarTy ty = True       --      C (a ty1 .. tyn)
+  | otherwise                   -- where a is a type variable
+  = case tcSplitAppTy_maybe ty of
+       Just (ty, _) -> hasTyVarHead ty
+       Nothing      -> False
+
 evVarPred_maybe :: EvVar -> Maybe PredType
 evVarPred_maybe v = if isPredTy ty then Just ty else Nothing
   where ty = varType v
index 53b492d..3225b28 100644 (file)
@@ -23,13 +23,14 @@ import TcSimplify ( simplifyAmbiguityCheck )
 import TypeRep
 import TcType
 import TcMType
-import TysWiredIn ( coercibleClass )
+import TysWiredIn ( coercibleClass, eqTyConName )
 import Type
 import Unify( tcMatchTyX )
 import Kind
 import CoAxiom
 import Class
 import TyCon
+import PrelNames( eqTyConKey )
 
 -- others:
 import HsSyn            -- HsType
@@ -44,6 +45,7 @@ import Util
 import ListSetOps
 import SrcLoc
 import Outputable
+import Unique           ( hasKey )
 import BasicTypes       ( IntWithInf, infinity )
 import FastString
 
@@ -593,6 +595,7 @@ check_valid_theta ctxt theta
   = do { dflags <- getDynFlags
        ; warnTc (wopt Opt_WarnDuplicateConstraints dflags &&
                  notNull dups) (dupPredWarn dups)
+       ; traceTc "check_valid_theta" (ppr theta)
        ; mapM_ (check_pred_ty dflags ctxt) theta }
   where
     (_,dups) = removeDups cmpPred theta
@@ -612,46 +615,29 @@ check_pred_help :: Bool    -- True <=> under a type synonym
                 -> DynFlags -> UserTypeCtxt
                 -> PredType -> TcM ()
 check_pred_help under_syn dflags ctxt pred
-  | Just pred' <- coreView pred
-  = check_pred_help True dflags ctxt pred'
+  | Just pred' <- coreView pred  -- Switch on under_syn when going under a
+                                 -- synonym (Trac #9838, yuk)
+  = check_pred_help True dflags ctxt pred'  
   | otherwise
-  = case classifyPredType pred of
-      ClassPred cls tys     -> check_class_pred dflags ctxt pred cls tys
-      EqPred NomEq _ _      -> check_eq_pred    dflags pred
-      EqPred ReprEq ty1 ty2 -> check_repr_eq_pred dflags ctxt pred ty1 ty2
-      TuplePred tys         -> check_tuple_pred under_syn dflags ctxt pred tys
-      IrredPred _           -> check_irred_pred under_syn dflags ctxt pred
-
-check_class_pred :: DynFlags -> UserTypeCtxt -> PredType -> Class -> [TcType] -> TcM ()
-check_class_pred dflags ctxt pred cls tys
-  = do {        -- Class predicates are valid in all contexts
-       ; checkTc (arity == n_tys) arity_err
-
-       ; checkTc (not (isIPClass cls) || okIPCtxt ctxt)
-                 (badIPPred pred)
-
-                -- Check the form of the argument types
-       ; check_class_pred_tys dflags ctxt pred tys
-       }
-  where
-    class_name = className cls
-    arity      = classArity cls
-    n_tys      = length tys
-    arity_err  = arityErr "Class" class_name arity n_tys
-
-check_eq_pred :: DynFlags -> PredType -> TcM ()
-check_eq_pred dflags pred
+  = case splitTyConApp_maybe pred of
+      Just (tc, tys) | Just cls <- tyConClass_maybe tc
+                     -> check_class_pred dflags ctxt pred cls tys  -- Includes Coercible
+                     | tc `hasKey` eqTyConKey
+                     -> check_eq_pred dflags pred tys
+                     | isTupleTyCon tc
+                     -> check_tuple_pred under_syn dflags ctxt pred tys
+      _ -> check_irred_pred under_syn dflags ctxt pred
+
+check_eq_pred :: DynFlags -> PredType -> [TcType] -> TcM ()
+check_eq_pred dflags pred tys
   =         -- Equational constraints are valid in all contexts if type
             -- families are permitted
-    checkTc (xopt Opt_TypeFamilies dflags || xopt Opt_GADTs dflags)
-            (eqPredTyErr pred)
-
-check_repr_eq_pred :: DynFlags -> UserTypeCtxt -> PredType
-                   -> TcType -> TcType -> TcM ()
-check_repr_eq_pred dflags ctxt pred ty1 ty2
-  = check_class_pred_tys dflags ctxt pred tys
+    do { checkTc (n_tys == 3)
+                 (arityErr "Equality constraint" eqTyConName 3 n_tys)
+       ; checkTc (xopt Opt_TypeFamilies dflags || xopt Opt_GADTs dflags)
+                 (eqPredTyErr pred) }
   where
-    tys = [ty1, ty2]
+    n_tys = length tys
 
 check_tuple_pred :: Bool -> DynFlags -> UserTypeCtxt -> PredType -> [PredType] -> TcM ()
 check_tuple_pred under_syn dflags ctxt pred ts
@@ -670,7 +656,7 @@ check_irred_pred under_syn dflags ctxt pred
          --   see Note [ConstraintKinds in predicates]
          -- But (X t1 t2) is always ok because we just require ConstraintKinds
          -- at the definition site (Trac #9838)
-        checkTc (under_syn || xopt Opt_ConstraintKinds dflags || not (tyvar_head pred))
+        checkTc (under_syn || xopt Opt_ConstraintKinds dflags || not (hasTyVarHead pred))
                 (predIrredErr pred)
 
          -- Make sure it is OK to have an irred pred in this context
@@ -708,32 +694,30 @@ It is equally dangerous to allow them in instance heads because in that case the
 Paterson conditions may not detect duplication of a type variable or size change. -}
 
 -------------------------
-check_class_pred_tys :: DynFlags -> UserTypeCtxt
-                     -> PredType -> [KindOrType] -> TcM ()
-check_class_pred_tys dflags ctxt pred kts
-  = checkTc pred_ok (predTyVarErr pred $$ how_to_allow)
-  where
-    (_, tys) = span isKind kts  -- see Note [Kind polymorphic type classes]
-    flexible_contexts = xopt Opt_FlexibleContexts dflags
-    undecidable_ok = xopt Opt_UndecidableInstances dflags
+check_class_pred :: DynFlags -> UserTypeCtxt -> PredType -> Class -> [TcType] -> TcM ()
+check_class_pred dflags ctxt pred cls tys
+  | isIPClass cls
+  = do { checkTc (arity == n_tys) arity_err
+       ; checkTc (okIPCtxt ctxt)  (badIPPred pred) }
 
-    pred_ok = case ctxt of
-        SpecInstCtxt -> True    -- {-# SPECIALISE instance Eq (T Int) #-} is fine
-        InstDeclCtxt -> flexible_contexts || undecidable_ok || all tcIsTyVarTy tys
-                                -- Further checks on head and theta in
-                                -- checkInstTermination
-        _             -> flexible_contexts || all tyvar_head tys
-    how_to_allow = parens (ptext (sLit "Use FlexibleContexts to permit this"))
+  | otherwise
+  = do { checkTc (arity == n_tys) arity_err
+       ; checkTc arg_tys_ok (predTyVarErr pred) }
+  where
+    class_name = className cls
+    arity      = classArity cls
+    n_tys      = length tys
+    arity_err  = arityErr "Class" class_name arity n_tys
 
+    flexible_contexts = xopt Opt_FlexibleContexts     dflags
+    undecidable_ok    = xopt Opt_UndecidableInstances dflags
 
--------------------------
-tyvar_head :: Type -> Bool
-tyvar_head ty                   -- Haskell 98 allows predicates of form
-  | tcIsTyVarTy ty = True       --      C (a ty1 .. tyn)
-  | otherwise                   -- where a is a type variable
-  = case tcSplitAppTy_maybe ty of
-        Just (ty, _) -> tyvar_head ty
-        Nothing      -> False
+    arg_tys_ok = case ctxt of
+        SpecInstCtxt -> True    -- {-# SPECIALISE instance Eq (T Int) #-} is fine
+        InstDeclCtxt -> checkValidClsArgs (flexible_contexts || undecidable_ok) tys
+                                -- Further checks on head and theta
+                                -- in checkInstTermination
+        _            -> checkValidClsArgs flexible_contexts tys
 
 -------------------------
 okIPCtxt :: UserTypeCtxt -> Bool
@@ -776,8 +760,9 @@ eqPredTyErr, predTyVarErr, predTupleErr, predIrredErr, predIrredBadCtxtErr :: Pr
 eqPredTyErr  pred = ptext (sLit "Illegal equational constraint") <+> pprType pred
                     $$
                     parens (ptext (sLit "Use GADTs or TypeFamilies to permit this"))
-predTyVarErr pred  = hang (ptext (sLit "Non type-variable argument"))
-                        2 (ptext (sLit "in the constraint:") <+> pprType pred)
+predTyVarErr pred  = vcat [ hang (ptext (sLit "Non type-variable argument"))
+                               2 (ptext (sLit "in the constraint:") <+> pprType pred)
+                          , parens (ptext (sLit "Use FlexibleContexts to permit this")) ]
 predTupleErr pred  = hang (ptext (sLit "Illegal tuple constraint:") <+> pprType pred)
                         2 (parens constraintKindsMsg)
 predIrredErr pred  = hang (ptext (sLit "Illegal constraint:") <+> pprType pred)
diff --git a/testsuite/tests/typecheck/should_fail/T10351.hs b/testsuite/tests/typecheck/should_fail/T10351.hs
new file mode 100644 (file)
index 0000000..411698b
--- /dev/null
@@ -0,0 +1,6 @@
+module T10351 where
+
+class C a where
+  op :: a -> ()
+
+f x = op [x]
diff --git a/testsuite/tests/typecheck/should_fail/T10351.stderr b/testsuite/tests/typecheck/should_fail/T10351.stderr
new file mode 100644 (file)
index 0000000..178005a
--- /dev/null
@@ -0,0 +1,5 @@
+\r
+T10351.hs:6:7: error:\r
+    No instance for (C [t]) arising from a use of ‘op’\r
+    In the expression: op [x]\r
+    In an equation for ‘f’: f x = op [x]\r
index 4408910..7d12b8f 100644 (file)
@@ -1,6 +1,7 @@
-
-T6022.hs:3:1:
-    Non type-variable argument in the constraint: Eq ([a] -> a)
-    (Use FlexibleContexts to permit this)
-    When checking that ‘f’ has the inferred type
-      f :: forall a. Eq ([a] -> a) => ([a] -> a) -> Bool
+\r
+T6022.hs:3:9: error:\r
+    No instance for (Eq ([a] -> a))\r
+      (maybe you haven't applied a function to enough arguments?)\r
+      arising from a use of ‘==’\r
+    In the expression: x == head\r
+    In an equation for ‘f’: f x = x == head\r
index 27b4d94..dc4bdfc 100644 (file)
@@ -1,8 +1,10 @@
-
-T8883.hs:20:1:
-    Non type-variable argument in the constraint: Functor (PF a)
-    (Use FlexibleContexts to permit this)
-    When checking that ‘fold’ has the inferred type
-      fold :: forall b a.
-              (Functor (PF a), Regular a) =>
-              (PF a b -> b) -> a -> b
+\r
+T8883.hs:20:14: error:\r
+    Could not deduce (Functor (PF a)) arising from a use of ‘fmap’\r
+    from the context: Regular a\r
+      bound by the inferred type of\r
+               fold :: Regular a => (PF a b -> b) -> a -> b\r
+      at T8883.hs:20:1-33\r
+    In the first argument of ‘(.)’, namely ‘fmap (fold f)’\r
+    In the second argument of ‘(.)’, namely ‘fmap (fold f) . from’\r
+    In the expression: f . fmap (fold f) . from\r
index faca079..b9c7d5a 100644 (file)
@@ -364,3 +364,4 @@ test('T9858e', normal, compile_fail, [''])
 test('T10285',
      extra_clean(['T10285a.hi', 'T10285a.o']),
      multimod_compile_fail, ['T10285', '-v0'])
+test('T10351', normal, compile_fail, [''])
index b23e9d9..3a2e5a5 100644 (file)
@@ -1,7 +1,6 @@
-
-tcfail108.hs:7:10:
-    Non type-variable argument in the constraint: Eq (f (Rec f))
-    (Use FlexibleContexts to permit this)
-    In the context: Eq (f (Rec f))
-    While checking an instance declaration
-    In the instance declaration for ‘Eq (Rec f)’
+\r
+tcfail108.hs:7:10: error:\r
+    Variable ‘f’ occurs more often than in the instance head\r
+      in the constraint: Eq (f (Rec f))\r
+    (Use UndecidableInstances to permit this)\r
+    In the instance declaration for ‘Eq (Rec f)’\r