summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2015-04-30 09:18:49 +0100
committerSimon Peyton Jones <simonpj@microsoft.com>2015-04-30 09:22:20 +0100
commitb83160d07e626bee685f329a9a73e90a4a6074ae (patch)
treeaba7948b3d73a3b05db887da48905fec73c62e69 /compiler
parent54cefbd753b516fe8645c1470750ad7f65352844 (diff)
downloadhaskell-b83160d07e626bee685f329a9a73e90a4a6074ae.tar.gz
Tidy up treatment of FlexibleContexts
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.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/main/DynFlags.hs5
-rw-r--r--compiler/typecheck/TcBinds.hs5
-rw-r--r--compiler/typecheck/TcSimplify.hs57
-rw-r--r--compiler/typecheck/TcType.hs31
-rw-r--r--compiler/typecheck/TcValidity.hs111
5 files changed, 117 insertions, 92 deletions
diff --git a/compiler/main/DynFlags.hs b/compiler/main/DynFlags.hs
index 094984be2e..f078c5162a 100644
--- a/compiler/main/DynFlags.hs
+++ b/compiler/main/DynFlags.hs
@@ -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)
diff --git a/compiler/typecheck/TcBinds.hs b/compiler/typecheck/TcBinds.hs
index 17f60787c6..64333ebdb3 100644
--- a/compiler/typecheck/TcBinds.hs
+++ b/compiler/typecheck/TcBinds.hs
@@ -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) $
diff --git a/compiler/typecheck/TcSimplify.hs b/compiler/typecheck/TcSimplify.hs
index 5f9f417e1c..c1535f8733 100644
--- a/compiler/typecheck/TcSimplify.hs
+++ b/compiler/typecheck/TcSimplify.hs
@@ -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]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/compiler/typecheck/TcType.hs b/compiler/typecheck/TcType.hs
index 4185be8214..4d4f6823f2 100644
--- a/compiler/typecheck/TcType.hs
+++ b/compiler/typecheck/TcType.hs
@@ -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
diff --git a/compiler/typecheck/TcValidity.hs b/compiler/typecheck/TcValidity.hs
index 53b492d3e6..3225b2848b 100644
--- a/compiler/typecheck/TcValidity.hs
+++ b/compiler/typecheck/TcValidity.hs
@@ -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)