summaryrefslogtreecommitdiff
path: root/compiler/typecheck/TcCanonical.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/typecheck/TcCanonical.hs')
-rw-r--r--compiler/typecheck/TcCanonical.hs1242
1 files changed, 879 insertions, 363 deletions
diff --git a/compiler/typecheck/TcCanonical.hs b/compiler/typecheck/TcCanonical.hs
index be51914a27..6579556843 100644
--- a/compiler/typecheck/TcCanonical.hs
+++ b/compiler/typecheck/TcCanonical.hs
@@ -4,11 +4,14 @@ module TcCanonical(
canonicalize,
unifyDerived,
makeSuperClasses, maybeSym,
- StopOrContinue(..), stopWith, continueWith
+ StopOrContinue(..), stopWith, continueWith,
+ solveCallStack -- For TcSimplify
) where
#include "HsVersions.h"
+import GhcPrelude
+
import TcRnTypes
import TcUnify( swapOverTyVars, metaTyVarUpdateOK )
import TcType
@@ -16,19 +19,24 @@ import Type
import TcFlatten
import TcSMonad
import TcEvidence
+import TcEvTerm
import Class
import TyCon
import TyCoRep -- cleverly decomposes types, good for completeness checking
+import TysWiredIn( cTupleTyConName )
import Coercion
+import CoreSyn
+import Id( idType, mkTemplateLocals )
import FamInstEnv ( FamInstEnvs )
import FamInst ( tcTopNormaliseNewTypeTF_maybe )
import Var
import VarEnv( mkInScopeSet )
-import VarSet( extendVarSetList )
+import VarSet( delVarSetList )
import Outputable
import DynFlags( DynFlags )
import NameSet
import RdrName
+import HsTypes( HsIPName(..) )
import Pair
import Util
@@ -75,10 +83,34 @@ last time through, so we can skip the classification step.
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
canonicalize :: Ct -> TcS (StopOrContinue Ct)
-canonicalize ct@(CNonCanonical { cc_ev = ev })
- = do { traceTcS "canonicalize (non-canonical)" (ppr ct)
- ; {-# SCC "canEvVar" #-}
- canEvNC ev }
+canonicalize (CNonCanonical { cc_ev = ev })
+ = {-# SCC "canNC" #-}
+ case classifyPredType pred of
+ ClassPred cls tys -> do traceTcS "canEvNC:cls" (ppr cls <+> ppr tys)
+ canClassNC ev cls tys
+ EqPred eq_rel ty1 ty2 -> do traceTcS "canEvNC:eq" (ppr ty1 $$ ppr ty2)
+ canEqNC ev eq_rel ty1 ty2
+ IrredPred {} -> do traceTcS "canEvNC:irred" (ppr pred)
+ canIrred ev
+ ForAllPred _ _ pred -> do traceTcS "canEvNC:forall" (ppr pred)
+ canForAll ev (isClassPred pred)
+ where
+ pred = ctEvPred ev
+
+canonicalize (CQuantCan (QCI { qci_ev = ev, qci_pend_sc = pend_sc }))
+ = canForAll ev pend_sc
+
+canonicalize (CIrredCan { cc_ev = ev })
+ | EqPred eq_rel ty1 ty2 <- classifyPredType (ctEvPred ev)
+ = -- For insolubles (all of which are equalities, do /not/ flatten the arguments
+ -- In Trac #14350 doing so led entire-unnecessary and ridiculously large
+ -- type function expansion. Instead, canEqNC just applies
+ -- the substitution to the predicate, and may do decomposition;
+ -- e.g. a ~ [a], where [G] a ~ [Int], can decompose
+ canEqNC ev eq_rel ty1 ty2
+
+ | otherwise
+ = canIrred ev
canonicalize (CDictCan { cc_ev = ev, cc_class = cls
, cc_tyargs = xis, cc_pend_sc = pend_sc })
@@ -101,21 +133,9 @@ canonicalize (CFunEqCan { cc_ev = ev
= {-# SCC "canEqLeafFunEq" #-}
canCFunEqCan ev fn xis1 fsk
-canonicalize (CIrredEvCan { cc_ev = ev })
- = canIrred ev
canonicalize (CHoleCan { cc_ev = ev, cc_hole = hole })
= canHole ev hole
-canEvNC :: CtEvidence -> TcS (StopOrContinue Ct)
--- Called only for non-canonical EvVars
-canEvNC ev
- = case classifyPredType (ctEvPred ev) of
- ClassPred cls tys -> do traceTcS "canEvNC:cls" (ppr cls <+> ppr tys)
- canClassNC ev cls tys
- EqPred eq_rel ty1 ty2 -> do traceTcS "canEvNC:eq" (ppr ty1 $$ ppr ty2)
- canEqNC ev eq_rel ty1 ty2
- IrredPred {} -> do traceTcS "canEvNC:irred" (ppr (ctEvPred ev))
- canIrred ev
{-
************************************************************************
* *
@@ -130,13 +150,51 @@ canClassNC :: CtEvidence -> Class -> [Type] -> TcS (StopOrContinue Ct)
-- Precondition: EvVar is class evidence
canClassNC ev cls tys
| isGiven ev -- See Note [Eagerly expand given superclasses]
- = do { sc_cts <- mkStrictSuperClasses ev cls tys
+ = do { sc_cts <- mkStrictSuperClasses ev [] [] cls tys
; emitWork sc_cts
; canClass ev cls tys False }
+
+ | isWanted ev
+ , Just ip_name <- isCallStackPred cls tys
+ , OccurrenceOf func <- ctLocOrigin loc
+ -- If we're given a CallStack constraint that arose from a function
+ -- call, we need to push the current call-site onto the stack instead
+ -- of solving it directly from a given.
+ -- See Note [Overview of implicit CallStacks] in TcEvidence
+ -- and Note [Solving CallStack constraints] in TcSMonad
+ = do { -- First we emit a new constraint that will capture the
+ -- given CallStack.
+ ; let new_loc = setCtLocOrigin loc (IPOccOrigin (HsIPName ip_name))
+ -- We change the origin to IPOccOrigin so
+ -- this rule does not fire again.
+ -- See Note [Overview of implicit CallStacks]
+
+ ; new_ev <- newWantedEvVarNC new_loc pred
+
+ -- Then we solve the wanted by pushing the call-site
+ -- onto the newly emitted CallStack
+ ; let ev_cs = EvCsPushCall func (ctLocSpan loc) (ctEvExpr new_ev)
+ ; solveCallStack ev ev_cs
+
+ ; canClass new_ev cls tys False }
+
| otherwise
= canClass ev cls tys (has_scs cls)
+
where
has_scs cls = not (null (classSCTheta cls))
+ loc = ctEvLoc ev
+ pred = ctEvPred ev
+
+solveCallStack :: CtEvidence -> EvCallStack -> TcS ()
+-- Also called from TcSimplify when defaulting call stacks
+solveCallStack ev ev_cs = do
+ -- We're given ev_cs :: CallStack, but the evidence term should be a
+ -- dictionary, so we have to coerce ev_cs to a dictionary for
+ -- `IP ip CallStack`. See Note [Overview of implicit CallStacks]
+ cs_tm <- evCallStack ev_cs
+ let ev_tm = mkEvCast cs_tm (wrapIP (ctEvPred ev))
+ setEvBindIfWanted ev ev_tm
canClass :: CtEvidence
-> Class -> [Type]
@@ -147,8 +205,9 @@ canClass :: CtEvidence
canClass ev cls tys pend_sc
= -- all classes do *nominal* matching
ASSERT2( ctEvRole ev == Nominal, ppr ev $$ ppr cls $$ ppr tys )
- do { (xis, cos) <- flattenManyNom ev tys
- ; let co = mkTcTyConAppCo Nominal (classTyCon cls) cos
+ do { (xis, cos, _kind_co) <- flattenArgsNom ev cls_tc tys
+ ; MASSERT( isTcReflCo _kind_co )
+ ; let co = mkTcTyConAppCo Nominal cls_tc cos
xi = mkClassPred cls xis
mk_ct new_ev = CDictCan { cc_ev = new_ev
, cc_tyargs = xis
@@ -158,12 +217,14 @@ canClass ev cls tys pend_sc
; traceTcS "canClass" (vcat [ ppr ev
, ppr xi, ppr mb ])
; return (fmap mk_ct mb) }
+ where
+ cls_tc = classTyCon cls
{- Note [The superclass story]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We need to add superclass constraints for two reasons:
-* For givens [G], they give us a route to to proof. E.g.
+* For givens [G], they give us a route to proof. E.g.
f :: Ord a => a -> Bool
f x = x == x
We get a Wanted (Eq a), which can only be solved from the superclass
@@ -203,19 +264,19 @@ So here's the plan:
1. Eagerly generate superclasses for given (but not wanted)
constraints; see Note [Eagerly expand given superclasses].
- This is done in canClassNC, when we take a non-canonical constraint
- and cannonicalise it.
+ This is done using mkStrictSuperClasses in canClassNC, when
+ we take a non-canonical Given constraint and cannonicalise it.
However stop if you encounter the same class twice. That is,
- expand eagerly, but have a conservative termination condition: see
- Note [Expanding superclasses] in TcType.
+ mkStrictSuperClasses expands eagerly, but has a conservative
+ termination condition: see Note [Expanding superclasses] in TcType.
2. Solve the wanteds as usual, but do no further expansion of
superclasses for canonical CDictCans in solveSimpleGivens or
solveSimpleWanteds; Note [Danger of adding superclasses during solving]
- However, /do/ continue to eagerly expand superlasses for /given/
- non-canonical constraints (canClassNC does this). As Trac #12175
+ However, /do/ continue to eagerly expand superlasses for new /given/
+ /non-canonical/ constraints (canClassNC does this). As Trac #12175
showed, a type-family application can expand to a class constraint,
and we want to see its superclasses for just the same reason as
Note [Eagerly expand given superclasses].
@@ -223,9 +284,20 @@ So here's the plan:
3. If we have any remaining unsolved wanteds
(see Note [When superclasses help] in TcRnTypes)
try harder: take both the Givens and Wanteds, and expand
- superclasses again. This may succeed in generating (a finite
- number of) extra Givens, and extra Deriveds. Both may help the
- proof. This is done in TcSimplify.expandSuperClasses.
+ superclasses again. See the calls to expandSuperClasses in
+ TcSimplify.simpl_loop and solveWanteds.
+
+ This may succeed in generating (a finite number of) extra Givens,
+ and extra Deriveds. Both may help the proof.
+
+3a An important wrinkle: only expand Givens from the current level.
+ Two reasons:
+ - We only want to expand it once, and that is best done at
+ the level it is bound, rather than repeatedly at the leaves
+ of the implication tree
+ - We may be inside a type where we can't create term-level
+ evidence anyway, so we can't superclass-expand, say,
+ (a ~ b) to get (a ~# b). This happened in Trac #15290.
4. Go round to (2) again. This loop (2,3,4) is implemented
in TcSimplify.simpl_loop.
@@ -247,10 +319,31 @@ Why do we do this? Two reasons:
When we take a CNonCanonical or CIrredCan, but end up classifying it
as a CDictCan, we set the cc_pend_sc flag to False.
+Note [Superclass loops]
+~~~~~~~~~~~~~~~~~~~~~~~
+Suppose we have
+ class C a => D a
+ class D a => C a
+
+Then, when we expand superclasses, we'll get back to the self-same
+predicate, so we have reached a fixpoint in expansion and there is no
+point in fruitlessly expanding further. This case just falls out from
+our strategy. Consider
+ f :: C a => a -> Bool
+ f x = x==x
+Then canClassNC gets the [G] d1: C a constraint, and eager emits superclasses
+G] d2: D a, [G] d3: C a (psc). (The "psc" means it has its sc_pend flag set.)
+When processing d3 we find a match with d1 in the inert set, and we always
+keep the inert item (d1) if possible: see Note [Replacement vs keeping] in
+TcInteract. So d3 dies a quick, happy death.
+
Note [Eagerly expand given superclasses]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In step (1) of Note [The superclass story], why do we eagerly expand
-Given superclasses by one layer? Mainly because of some very obscure
+Given superclasses by one layer? (By "one layer" we mean expand transitively
+until you meet the same class again -- the conservative criterion embodied
+in expandSuperClasses. So a "layer" might be a whole stack of superclasses.)
+We do this eagerly for Givens mainly because of some very obscure
cases like this:
instance Bad a => Eq (T a)
@@ -295,7 +388,7 @@ Examples of how adding superclasses can help:
Follow the superclass rules to add
[G] F a ~ b
[D] F a ~ beta
- Now we we get [D] beta ~ b, and can solve that.
+ Now we get [D] beta ~ b, and can solve that.
-- Example (tcfail138)
class L a b | a -> b
@@ -360,67 +453,67 @@ makeSuperClasses :: [Ct] -> TcS [Ct]
makeSuperClasses cts = concatMapM go cts
where
go (CDictCan { cc_ev = ev, cc_class = cls, cc_tyargs = tys })
- = mkStrictSuperClasses ev cls tys
+ = mkStrictSuperClasses ev [] [] cls tys
+ go (CQuantCan (QCI { qci_pred = pred, qci_ev = ev }))
+ = ASSERT2( isClassPred pred, ppr pred ) -- The cts should all have
+ -- class pred heads
+ mkStrictSuperClasses ev tvs theta cls tys
+ where
+ (tvs, theta, cls, tys) = tcSplitDFunTy (ctEvPred ev)
go ct = pprPanic "makeSuperClasses" (ppr ct)
-mkStrictSuperClasses :: CtEvidence -> Class -> [Type] -> TcS [Ct]
--- Return constraints for the strict superclasses of (c tys)
-mkStrictSuperClasses ev cls tys
- = mk_strict_superclasses (unitNameSet (className cls)) ev cls tys
-
-mk_superclasses :: NameSet -> CtEvidence -> TcS [Ct]
--- Return this constraint, plus its superclasses, if any
-mk_superclasses rec_clss ev
- | ClassPred cls tys <- classifyPredType (ctEvPred ev)
- = mk_superclasses_of rec_clss ev cls tys
-
- | otherwise -- Superclass is not a class predicate
- = return [mkNonCanonical ev]
-
-mk_superclasses_of :: NameSet -> CtEvidence -> Class -> [Type] -> TcS [Ct]
--- Always return this class constraint,
--- and expand its superclasses
-mk_superclasses_of rec_clss ev cls tys
- | loop_found = do { traceTcS "mk_superclasses_of: loop" (ppr cls <+> ppr tys)
- ; return [this_ct] } -- cc_pend_sc of this_ct = True
- | otherwise = do { traceTcS "mk_superclasses_of" (vcat [ ppr cls <+> ppr tys
- , ppr (isCTupleClass cls)
- , ppr rec_clss
- ])
- ; sc_cts <- mk_strict_superclasses rec_clss' ev cls tys
- ; return (this_ct : sc_cts) }
- -- cc_pend_sc of this_ct = False
- where
- cls_nm = className cls
- loop_found = not (isCTupleClass cls) && cls_nm `elemNameSet` rec_clss
- -- Tuples never contribute to recursion, and can be nested
- rec_clss' = rec_clss `extendNameSet` cls_nm
- this_ct = CDictCan { cc_ev = ev, cc_class = cls, cc_tyargs = tys
- , cc_pend_sc = loop_found }
- -- NB: If there is a loop, we cut off, so we have not
- -- added the superclasses, hence cc_pend_sc = True
-
-mk_strict_superclasses :: NameSet -> CtEvidence -> Class -> [Type] -> TcS [Ct]
+mkStrictSuperClasses
+ :: CtEvidence
+ -> [TyVar] -> ThetaType -- These two args are non-empty only when taking
+ -- superclasses of a /quantified/ constraint
+ -> Class -> [Type] -> TcS [Ct]
+-- Return constraints for the strict superclasses of
+-- ev :: forall as. theta => cls tys
+mkStrictSuperClasses ev tvs theta cls tys
+ = mk_strict_superclasses (unitNameSet (className cls))
+ ev tvs theta cls tys
+
+mk_strict_superclasses :: NameSet -> CtEvidence
+ -> [TyVar] -> ThetaType
+ -> Class -> [Type] -> TcS [Ct]
-- Always return the immediate superclasses of (cls tys);
-- and expand their superclasses, provided none of them are in rec_clss
-- nor are repeated
-mk_strict_superclasses rec_clss ev cls tys
+mk_strict_superclasses rec_clss ev tvs theta cls tys
| CtGiven { ctev_evar = evar, ctev_loc = loc } <- ev
- = do { sc_evs <- newGivenEvVars (mk_given_loc loc)
- (mkEvScSelectors (EvId evar) cls tys)
- ; concatMapM (mk_superclasses rec_clss) sc_evs }
+ = concatMapM (do_one_given evar (mk_given_loc loc)) $
+ classSCSelIds cls
+ where
+ dict_ids = mkTemplateLocals theta
+ size = sizeTypes tys
+
+ do_one_given evar given_loc sel_id
+ | not (null tvs)
+ , null theta
+ , isUnliftedType sc_pred
+ -- Very special case for equality
+ -- See Note [Equality superclasses in quantified constraints]
+ = do { empty_ctuple_cls <- tcLookupClass (cTupleTyConName 0)
+ ; let theta1 = [mkClassPred empty_ctuple_cls []]
+ dict_ids1 = mkTemplateLocals theta1
+ ; given_ev <- new_given theta1 dict_ids1 []
+ ; return [mkNonCanonical given_ev] }
+
+ | otherwise -- Normal case
+ = do { given_ev <- new_given theta dict_ids dict_ids
+ ; mk_superclasses rec_clss given_ev tvs theta sc_pred }
- | all noFreeVarsOfType tys
- = return [] -- Wanteds with no variables yield no deriveds.
- -- See Note [Improvement from Ground Wanteds]
+ where
+ sc_pred = funResultTy (piResultTys (idType sel_id) tys)
+
+ new_given theta_abs dict_ids_abs dict_ids_app
+ = newGivenEvVar given_loc (given_ty, given_ev)
+ where
+ given_ty = mkInfSigmaTy tvs theta_abs sc_pred
+ given_ev = EvExpr $ mkLams tvs $ mkLams dict_ids_abs $
+ Var sel_id `mkTyApps` tys `App`
+ (evId evar `mkTyApps` mkTyVarTys tvs `mkVarApps` dict_ids_app)
- | otherwise -- Wanted/Derived case, just add Derived superclasses
- -- that can lead to improvement.
- = do { let loc = ctEvLoc ev
- ; sc_evs <- mapM (newDerivedNC loc) (immSuperClasses cls tys)
- ; concatMapM (mk_superclasses rec_clss) sc_evs }
- where
- size = sizeTypes tys
mk_given_loc loc
| isCTupleClass cls
= loc -- For tuple predicates, just take them apart, without
@@ -439,8 +532,103 @@ mk_strict_superclasses rec_clss ev cls tys
| otherwise -- Probably doesn't happen, since this function
= loc -- is only used for Givens, but does no harm
+mk_strict_superclasses rec_clss ev tvs theta cls tys
+ | all noFreeVarsOfType tys
+ = return [] -- Wanteds with no variables yield no deriveds.
+ -- See Note [Improvement from Ground Wanteds]
+
+ | otherwise -- Wanted/Derived case, just add Derived superclasses
+ -- that can lead to improvement.
+ = ASSERT2( null tvs && null theta, ppr tvs $$ ppr theta )
+ concatMapM do_one_derived (immSuperClasses cls tys)
+ where
+ loc = ctEvLoc ev
+
+ do_one_derived sc_pred
+ = do { sc_ev <- newDerivedNC loc sc_pred
+ ; mk_superclasses rec_clss sc_ev [] [] sc_pred }
+
+mk_superclasses :: NameSet -> CtEvidence
+ -> [TyVar] -> ThetaType -> PredType -> TcS [Ct]
+-- Return this constraint, plus its superclasses, if any
+mk_superclasses rec_clss ev tvs theta pred
+ | ClassPred cls tys <- classifyPredType pred
+ = mk_superclasses_of rec_clss ev tvs theta cls tys
+
+ | otherwise -- Superclass is not a class predicate
+ = return [mkNonCanonical ev]
+
+mk_superclasses_of :: NameSet -> CtEvidence
+ -> [TyVar] -> ThetaType -> Class -> [Type]
+ -> TcS [Ct]
+-- Always return this class constraint,
+-- and expand its superclasses
+mk_superclasses_of rec_clss ev tvs theta cls tys
+ | loop_found = do { traceTcS "mk_superclasses_of: loop" (ppr cls <+> ppr tys)
+ ; return [this_ct] } -- cc_pend_sc of this_ct = True
+ | otherwise = do { traceTcS "mk_superclasses_of" (vcat [ ppr cls <+> ppr tys
+ , ppr (isCTupleClass cls)
+ , ppr rec_clss
+ ])
+ ; sc_cts <- mk_strict_superclasses rec_clss' ev tvs theta cls tys
+ ; return (this_ct : sc_cts) }
+ -- cc_pend_sc of this_ct = False
+ where
+ cls_nm = className cls
+ loop_found = not (isCTupleClass cls) && cls_nm `elemNameSet` rec_clss
+ -- Tuples never contribute to recursion, and can be nested
+ rec_clss' = rec_clss `extendNameSet` cls_nm
+
+ this_ct | null tvs, null theta
+ = CDictCan { cc_ev = ev, cc_class = cls, cc_tyargs = tys
+ , cc_pend_sc = loop_found }
+ -- NB: If there is a loop, we cut off, so we have not
+ -- added the superclasses, hence cc_pend_sc = True
+ | otherwise
+ = CQuantCan (QCI { qci_tvs = tvs, qci_pred = mkClassPred cls tys
+ , qci_ev = ev
+ , qci_pend_sc = loop_found })
+
+
+{- Note [Equality superclasses in quantified constraints]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider (Trac #15359, #15593, #15625)
+ f :: (forall a. theta => a ~ b) => stuff
+
+It's a bit odd to have a local, quantified constraint for `(a~b)`,
+but some people want such a thing (see the tickets). And for
+Coercible it is definitely useful
+ f :: forall m. (forall p q. Coercible p q => Coercible (m p) (m q)))
+ => stuff
+
+Moreover it's not hard to arrange; we just need to look up /equality/
+constraints in the quantified-constraint environment, which we do in
+TcInteract.doTopReactOther.
+
+There is a wrinkle though, in the case where 'theta' is empty, so
+we have
+ f :: (forall a. a~b) => stuff
+
+Now the superclass machinery kicks in, in makeSuperClasses,
+giving us a a second quantified constrait
+ (forall a. a ~# b)
+BUT this is an unboxed value! And nothing has prepared us for
+dictionary "functions" that are unboxed. Actually it does just
+about work, but the simplier ends up with stuff like
+ case (/\a. eq_sel d) of df -> ...(df @Int)...
+and fails to simplify that any further.
+
+It seems eaiser to give such unboxed quantifed constraints a
+dummmy () argument, thus
+ (forall a. (% %) => a ~# b)
+where (% %) is the empty constraint tuple. That makes everything
+be nicely boxed.
+
+(One might wonder about using void# instead, but this seems more
+uniform -- it's a constraint argument -- and I'm not worried about
+the last drop of efficiency for this very rare case.)
+
-{-
************************************************************************
* *
* Irreducibles canonicalization
@@ -450,28 +638,182 @@ mk_strict_superclasses rec_clss ev cls tys
canIrred :: CtEvidence -> TcS (StopOrContinue Ct)
-- Precondition: ty not a tuple and no other evidence form
-canIrred old_ev
- = do { let old_ty = ctEvPred old_ev
- ; traceTcS "can_pred" (text "IrredPred = " <+> ppr old_ty)
- ; (xi,co) <- flatten FM_FlattenAll old_ev old_ty -- co :: xi ~ old_ty
- ; rewriteEvidence old_ev xi co `andWhenContinue` \ new_ev ->
+canIrred ev
+ = do { let pred = ctEvPred ev
+ ; traceTcS "can_pred" (text "IrredPred = " <+> ppr pred)
+ ; (xi,co) <- flatten FM_FlattenAll ev pred -- co :: xi ~ pred
+ ; rewriteEvidence ev xi co `andWhenContinue` \ new_ev ->
do { -- Re-classify, in case flattening has improved its shape
; case classifyPredType (ctEvPred new_ev) of
ClassPred cls tys -> canClassNC new_ev cls tys
EqPred eq_rel ty1 ty2 -> canEqNC new_ev eq_rel ty1 ty2
_ -> continueWith $
- CIrredEvCan { cc_ev = new_ev } } }
+ mkIrredCt new_ev } }
canHole :: CtEvidence -> Hole -> TcS (StopOrContinue Ct)
canHole ev hole
- = do { let ty = ctEvPred ev
- ; (xi,co) <- flatten FM_SubstOnly ev ty -- co :: xi ~ ty
+ = do { let pred = ctEvPred ev
+ ; (xi,co) <- flatten FM_SubstOnly ev pred -- co :: xi ~ pred
; rewriteEvidence ev xi co `andWhenContinue` \ new_ev ->
- do { emitInsoluble (CHoleCan { cc_ev = new_ev
- , cc_hole = hole })
+ do { updInertIrreds (`snocCts` (CHoleCan { cc_ev = new_ev
+ , cc_hole = hole }))
; stopWith new_ev "Emit insoluble hole" } }
-{-
+
+{- *********************************************************************
+* *
+* Quantified predicates
+* *
+********************************************************************* -}
+
+{- Note [Quantified constraints]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The -XQuantifiedConstraints extension allows type-class contexts like this:
+
+ data Rose f x = Rose x (f (Rose f x))
+
+ instance (Eq a, forall b. Eq b => Eq (f b))
+ => Eq (Rose f a) where
+ (Rose x1 rs1) == (Rose x2 rs2) = x1==x2 && rs1 == rs2
+
+Note the (forall b. Eq b => Eq (f b)) in the instance contexts.
+This quantified constraint is needed to solve the
+ [W] (Eq (f (Rose f x)))
+constraint which arises form the (==) definition.
+
+The wiki page is
+ https://ghc.haskell.org/trac/ghc/wiki/QuantifiedConstraints
+which in turn contains a link to the GHC Proposal where the change
+is specified, and a Haskell Symposium paper about it.
+
+We implement two main extensions to the design in the paper:
+
+ 1. We allow a variable in the instance head, e.g.
+ f :: forall m a. (forall b. m b) => D (m a)
+ Notice the 'm' in the head of the quantified constraint, not
+ a class.
+
+ 2. We suport superclasses to quantified constraints.
+ For example (contrived):
+ f :: (Ord b, forall b. Ord b => Ord (m b)) => m a -> m a -> Bool
+ f x y = x==y
+ Here we need (Eq (m a)); but the quantifed constraint deals only
+ with Ord. But we can make it work by using its superclass.
+
+Here are the moving parts
+ * Language extension {-# LANGUAGE QuantifiedConstraints #-}
+ and add it to ghc-boot-th:GHC.LanguageExtensions.Type.Extension
+
+ * A new form of evidence, EvDFun, that is used to discharge
+ such wanted constraints
+
+ * checkValidType gets some changes to accept forall-constraints
+ only in the right places.
+
+ * Type.PredTree gets a new constructor ForAllPred, and
+ and classifyPredType analyses a PredType to decompose
+ the new forall-constraints
+
+ * TcSMonad.InertCans gets an extra field, inert_insts,
+ which holds all the Given forall-constraints. In effect,
+ such Given constraints are like local instance decls.
+
+ * When trying to solve a class constraint, via
+ TcInteract.matchInstEnv, use the InstEnv from inert_insts
+ so that we include the local Given forall-constraints
+ in the lookup. (See TcSMonad.getInstEnvs.)
+
+ * TcCanonical.canForAll deals with solving a
+ forall-constraint. See
+ Note [Solving a Wanted forall-constraint]
+
+ * We augment the kick-out code to kick out an inert
+ forall constraint if it can be rewritten by a new
+ type equality; see TcSMonad.kick_out_rewritable
+
+Note that a quantified constraint is never /inferred/
+(by TcSimplify.simplifyInfer). A function can only have a
+quantified constraint in its type if it is given an explicit
+type signature.
+
+Note that we implement
+-}
+
+canForAll :: CtEvidence -> Bool -> TcS (StopOrContinue Ct)
+-- We have a constraint (forall as. blah => C tys)
+canForAll ev pend_sc
+ = do { -- First rewrite it to apply the current substitution
+ -- Do not bother with type-family reductions; we can't
+ -- do them under a forall anyway (c.f. Flatten.flatten_one
+ -- on a forall type)
+ let pred = ctEvPred ev
+ ; (xi,co) <- flatten FM_SubstOnly ev pred -- co :: xi ~ pred
+ ; rewriteEvidence ev xi co `andWhenContinue` \ new_ev ->
+
+ do { -- Now decompose into its pieces and solve it
+ -- (It takes a lot less code to flatten before decomposing.)
+ ; case classifyPredType (ctEvPred new_ev) of
+ ForAllPred tv_bndrs theta pred
+ -> solveForAll new_ev tv_bndrs theta pred pend_sc
+ _ -> pprPanic "canForAll" (ppr new_ev)
+ } }
+
+solveForAll :: CtEvidence -> [TyVarBinder] -> TcThetaType -> PredType -> Bool
+ -> TcS (StopOrContinue Ct)
+solveForAll ev tv_bndrs theta pred pend_sc
+ | CtWanted { ctev_dest = dest } <- ev
+ = -- See Note [Solving a Wanted forall-constraint]
+ do { let skol_info = QuantCtxtSkol
+ empty_subst = mkEmptyTCvSubst $ mkInScopeSet $
+ tyCoVarsOfTypes (pred:theta) `delVarSetList` tvs
+ ; (subst, skol_tvs) <- tcInstSkolTyVarsX empty_subst tvs
+ ; given_ev_vars <- mapM newEvVar (substTheta subst theta)
+
+ ; (w_id, ev_binds)
+ <- checkConstraintsTcS skol_info skol_tvs given_ev_vars $
+ do { wanted_ev <- newWantedEvVarNC loc $
+ substTy subst pred
+ ; return ( ctEvEvId wanted_ev
+ , unitBag (mkNonCanonical wanted_ev)) }
+
+ ; setWantedEvTerm dest $
+ EvFun { et_tvs = skol_tvs, et_given = given_ev_vars
+ , et_binds = ev_binds, et_body = w_id }
+
+ ; stopWith ev "Wanted forall-constraint" }
+
+ | isGiven ev -- See Note [Solving a Given forall-constraint]
+ = do { addInertForAll qci
+ ; stopWith ev "Given forall-constraint" }
+
+ | otherwise
+ = stopWith ev "Derived forall-constraint"
+ where
+ loc = ctEvLoc ev
+ tvs = binderVars tv_bndrs
+ qci = QCI { qci_ev = ev, qci_tvs = tvs
+ , qci_pred = pred, qci_pend_sc = pend_sc }
+
+{- Note [Solving a Wanted forall-constraint]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Solving a wanted forall (quantified) constraint
+ [W] df :: forall ab. (Eq a, Ord b) => C x a b
+is delightfully easy. Just build an implication constraint
+ forall ab. (g1::Eq a, g2::Ord b) => [W] d :: C x a
+and discharge df thus:
+ df = /\ab. \g1 g2. let <binds> in d
+where <binds> is filled in by solving the implication constraint.
+All the machinery is to hand; there is little to do.
+
+Note [Solving a Given forall-constraint]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+For a Given constraint
+ [G] df :: forall ab. (Eq a, Ord b) => C x a b
+we just add it to TcS's local InstEnv of known instances,
+via addInertForall. Then, if we look up (C x Int Bool), say,
+we'll find a match in the InstEnv.
+
+
************************************************************************
* *
* Equalities
@@ -556,11 +898,14 @@ can_eq_nc' True _rdr_env _envs ev ReprEq ty1 _ ty2 _
= canEqReflexive ev ReprEq ty1
-- When working with ReprEq, unwrap newtypes.
-can_eq_nc' _flat rdr_env envs ev ReprEq ty1 _ ty2 ps_ty2
- | Just stuff1 <- tcTopNormaliseNewTypeTF_maybe envs rdr_env ty1
+-- See Note [Unwrap newtypes first]
+can_eq_nc' _flat rdr_env envs ev eq_rel ty1 ps_ty1 ty2 ps_ty2
+ | ReprEq <- eq_rel
+ , Just stuff1 <- tcTopNormaliseNewTypeTF_maybe envs rdr_env ty1
= can_eq_newtype_nc ev NotSwapped ty1 stuff1 ty2 ps_ty2
-can_eq_nc' _flat rdr_env envs ev ReprEq ty1 ps_ty1 ty2 _
- | Just stuff2 <- tcTopNormaliseNewTypeTF_maybe envs rdr_env ty2
+
+ | ReprEq <- eq_rel
+ , Just stuff2 <- tcTopNormaliseNewTypeTF_maybe envs rdr_env ty2
= can_eq_newtype_nc ev IsSwapped ty2 stuff2 ty1 ps_ty1
-- Then, get rid of casts
@@ -569,6 +914,13 @@ can_eq_nc' flat _rdr_env _envs ev eq_rel (CastTy ty1 co1) _ ty2 ps_ty2
can_eq_nc' flat _rdr_env _envs ev eq_rel ty1 ps_ty1 (CastTy ty2 co2) _
= canEqCast flat ev eq_rel IsSwapped ty2 co2 ty1 ps_ty1
+-- NB: pattern match on True: we want only flat types sent to canEqTyVar.
+-- See also Note [No top-level newtypes on RHS of representational equalities]
+can_eq_nc' True _rdr_env _envs ev eq_rel (TyVarTy tv1) ps_ty1 ty2 ps_ty2
+ = canEqTyVar ev eq_rel NotSwapped tv1 ps_ty1 ty2 ps_ty2
+can_eq_nc' True _rdr_env _envs ev eq_rel ty1 ps_ty1 (TyVarTy tv2) ps_ty2
+ = canEqTyVar ev eq_rel IsSwapped tv2 ps_ty2 ty1 ps_ty1
+
----------------------
-- Otherwise try to decompose
----------------------
@@ -576,7 +928,7 @@ can_eq_nc' flat _rdr_env _envs ev eq_rel ty1 ps_ty1 (CastTy ty2 co2) _
-- Literals
can_eq_nc' _flat _rdr_env _envs ev eq_rel ty1@(LitTy l1) _ (LitTy l2) _
| l1 == l2
- = do { setEqIfWanted ev (mkReflCo (eqRelRole eq_rel) ty1)
+ = do { setEvBindIfWanted ev (evCoercion $ mkReflCo (eqRelRole eq_rel) ty1)
; stopWith ev "Equal LitTy" }
-- Try to decompose type constructor applications
@@ -595,32 +947,38 @@ can_eq_nc' _flat _rdr_env _envs ev eq_rel
-- See Note [Canonicalising type applications] about why we require flat types
can_eq_nc' True _rdr_env _envs ev eq_rel (AppTy t1 s1) _ ty2 _
- | Just (t2, s2) <- tcSplitAppTy_maybe ty2
- = can_eq_app ev eq_rel t1 s1 t2 s2
+ | NomEq <- eq_rel
+ , Just (t2, s2) <- tcSplitAppTy_maybe ty2
+ = can_eq_app ev t1 s1 t2 s2
can_eq_nc' True _rdr_env _envs ev eq_rel ty1 _ (AppTy t2 s2) _
- | Just (t1, s1) <- tcSplitAppTy_maybe ty1
- = can_eq_app ev eq_rel t1 s1 t2 s2
+ | NomEq <- eq_rel
+ , Just (t1, s1) <- tcSplitAppTy_maybe ty1
+ = can_eq_app ev t1 s1 t2 s2
-- No similarity in type structure detected. Flatten and try again.
can_eq_nc' False rdr_env envs ev eq_rel _ ps_ty1 _ ps_ty2
= do { (xi1, co1) <- flatten FM_FlattenAll ev ps_ty1
; (xi2, co2) <- flatten FM_FlattenAll ev ps_ty2
- ; rewriteEqEvidence ev NotSwapped xi1 xi2 co1 co2
- `andWhenContinue` \ new_ev ->
- can_eq_nc' True rdr_env envs new_ev eq_rel xi1 xi1 xi2 xi2 }
-
--- Type variable on LHS or RHS are last.
--- NB: pattern match on True: we want only flat types sent to canEqTyVar.
--- See also Note [No top-level newtypes on RHS of representational equalities]
-can_eq_nc' True _rdr_env _envs ev eq_rel (TyVarTy tv1) ps_ty1 ty2 ps_ty2
- = canEqTyVar ev eq_rel NotSwapped tv1 ps_ty1 ty2 ps_ty2
-can_eq_nc' True _rdr_env _envs ev eq_rel ty1 ps_ty1 (TyVarTy tv2) ps_ty2
- = canEqTyVar ev eq_rel IsSwapped tv2 ps_ty2 ty1 ps_ty1
+ ; new_ev <- rewriteEqEvidence ev NotSwapped xi1 xi2 co1 co2
+ ; can_eq_nc' True rdr_env envs new_ev eq_rel xi1 xi1 xi2 xi2 }
-- We've flattened and the types don't match. Give up.
-can_eq_nc' True _rdr_env _envs ev _eq_rel _ ps_ty1 _ ps_ty2
+can_eq_nc' True _rdr_env _envs ev eq_rel _ ps_ty1 _ ps_ty2
= do { traceTcS "can_eq_nc' catch-all case" (ppr ps_ty1 $$ ppr ps_ty2)
- ; canEqHardFailure ev ps_ty1 ps_ty2 }
+ ; case eq_rel of -- See Note [Unsolved equalities]
+ ReprEq -> continueWith (mkIrredCt ev)
+ NomEq -> continueWith (mkInsolubleCt ev) }
+ -- No need to call canEqFailure/canEqHardFailure because they
+ -- flatten, and the types involved here are already flat
+
+{- Note [Unsolved equalities]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+If we have an unsolved equality like
+ (a b ~R# Int)
+that is not necessarily insoluble! Maybe 'a' will turn out to be a newtype.
+So we want to make it a potentially-soluble Irred not an insoluble one.
+Missing this point is what caused Trac #15431
+-}
---------------------------------
can_eq_nc_forall :: CtEvidence -> EqRel
@@ -636,10 +994,9 @@ can_eq_nc_forall :: CtEvidence -> EqRel
can_eq_nc_forall ev eq_rel s1 s2
| CtWanted { ctev_loc = loc, ctev_dest = orig_dest } <- ev
- = do { let free_tvs1 = tyCoVarsOfType s1
- free_tvs2 = tyCoVarsOfType s2
- (bndrs1, phi1) = tcSplitForAllTyVarBndrs s1
- (bndrs2, phi2) = tcSplitForAllTyVarBndrs s2
+ = do { let free_tvs = tyCoVarsOfTypes [s1,s2]
+ (bndrs1, phi1) = tcSplitForAllVarBndrs s1
+ (bndrs2, phi2) = tcSplitForAllVarBndrs s2
; if not (equalLength bndrs1 bndrs2)
then do { traceTcS "Forall failure" $
vcat [ ppr s1, ppr s2, ppr bndrs1, ppr bndrs2
@@ -648,7 +1005,7 @@ can_eq_nc_forall ev eq_rel s1 s2
; canEqHardFailure ev s1 s2 }
else
do { traceTcS "Creating implication for polytype equality" $ ppr ev
- ; let empty_subst1 = mkEmptyTCvSubst $ mkInScopeSet free_tvs1
+ ; let empty_subst1 = mkEmptyTCvSubst $ mkInScopeSet free_tvs
; (subst1, skol_tvs) <- tcInstSkolTyVarsX empty_subst1 $
binderVars bndrs1
@@ -656,35 +1013,30 @@ can_eq_nc_forall ev eq_rel s1 s2
phi1' = substTy subst1 phi1
-- Unify the kinds, extend the substitution
+ go :: [TcTyVar] -> TCvSubst -> [TyVarBinder]
+ -> TcS (TcCoercion, Cts)
go (skol_tv:skol_tvs) subst (bndr2:bndrs2)
= do { let tv2 = binderVar bndr2
- ; kind_co <- unifyWanted loc Nominal
- (tyVarKind skol_tv)
- (substTy subst (tyVarKind tv2))
+ ; (kind_co, wanteds1) <- unify loc Nominal (tyVarKind skol_tv)
+ (substTy subst (tyVarKind tv2))
; let subst' = extendTvSubst subst tv2
(mkCastTy (mkTyVarTy skol_tv) kind_co)
- ; co <- go skol_tvs subst' bndrs2
- ; return (mkForAllCo skol_tv kind_co co) }
+ ; (co, wanteds2) <- go skol_tvs subst' bndrs2
+ ; return ( mkTcForAllCo skol_tv kind_co co
+ , wanteds1 `unionBags` wanteds2 ) }
-- Done: unify phi1 ~ phi2
go [] subst bndrs2
= ASSERT( null bndrs2 )
- unifyWanted loc (eqRelRole eq_rel)
- phi1' (substTy subst phi2)
+ unify loc (eqRelRole eq_rel) phi1' (substTy subst phi2)
go _ _ _ = panic "cna_eq_nc_forall" -- case (s:ss) []
- empty_subst2 = mkEmptyTCvSubst $ mkInScopeSet $
- free_tvs2 `extendVarSetList` skol_tvs
+ empty_subst2 = mkEmptyTCvSubst (getTCvInScope subst1)
- ; (implic, _ev_binds, all_co) <- buildImplication skol_info skol_tvs [] $
- go skol_tvs empty_subst2 bndrs2
- -- We have nowhere to put these bindings
- -- but TcSimplify.setImplicationStatus
- -- checks that we don't actually use them
- -- when skol_info = UnifyForAllSkol
+ ; all_co <- checkTvConstraintsTcS skol_info skol_tvs $
+ go skol_tvs empty_subst2 bndrs2
- ; updWorkListTcS (extendWorkListImplic implic)
; setWantedEq orig_dest all_co
; stopWith ev "Deferred polytype equality" } }
@@ -693,6 +1045,17 @@ can_eq_nc_forall ev eq_rel s1 s2
pprEq s1 s2 -- See Note [Do not decompose given polytype equalities]
; stopWith ev "Discard given polytype equality" }
+ where
+ unify :: CtLoc -> Role -> TcType -> TcType -> TcS (TcCoercion, Cts)
+ -- This version returns the wanted constraint rather
+ -- than putting it in the work list
+ unify loc role ty1 ty2
+ | ty1 `tcEqType` ty2
+ = return (mkTcReflCo role ty1, emptyBag)
+ | otherwise
+ = do { (wanted, co) <- newWantedEq loc role ty1 ty2
+ ; return (co, unitBag (mkNonCanonical wanted)) }
+
---------------------------------
-- | Compare types for equality, while zonking as necessary. Gives up
-- as soon as it finds that two types are not equal.
@@ -777,7 +1140,8 @@ zonk_eq_types = go
-> do { cts <- readTcRef ref
; case cts of
Flexi -> give_up
- Indirect ty' -> unSwap swapped go ty' ty }
+ Indirect ty' -> do { trace_indirect tv ty'
+ ; unSwap swapped go ty' ty } }
_ -> give_up
where
give_up = return $ Left $ unSwap swapped Pair (mkTyVarTy tv) ty
@@ -790,12 +1154,17 @@ zonk_eq_types = go
then go ty1' ty2'
else return $ Left (Pair (TyVarTy tv1) (TyVarTy tv2)) }
+ trace_indirect tv ty
+ = traceTcS "Following filled tyvar (zonk_eq_types)"
+ (ppr tv <+> equals <+> ppr ty)
+
quick_zonk tv = case tcTyVarDetails tv of
MetaTv { mtv_ref = ref }
-> do { cts <- readTcRef ref
; case cts of
Flexi -> return (TyVarTy tv, False)
- Indirect ty' -> return (ty', True) }
+ Indirect ty' -> do { trace_indirect tv ty'
+ ; return (ty', True) } }
_ -> return (TyVarTy tv, False)
-- This happens for type families, too. But recall that failure
@@ -824,7 +1193,26 @@ zonk_eq_types = go
combine_rev f (Right tys) (Left elt) = Left (f <$> elt <*> pure tys)
combine_rev f (Right tys) (Right ty) = Right (f ty tys)
-{-
+{- See Note [Unwrap newtypes first]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider
+ newtype N m a = MkN (m a)
+Then N will get a conservative, Nominal role for its second paramter 'a',
+because it appears as an argument to the unknown 'm'. Now consider
+ [W] N Maybe a ~R# N Maybe b
+
+If we decompose, we'll get
+ [W] a ~N# b
+
+But if instead we unwrap we'll get
+ [W] Maybe a ~R# Maybe b
+which in turn gives us
+ [W] a ~R# b
+which is easier to satisfy.
+
+Bottom line: unwrap newtypes before decomposing them!
+c.f. Trac #9123 comment:52,53 for a compelling example.
+
Note [Newtypes can blow the stack]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Suppose we have
@@ -865,7 +1253,7 @@ Here's another place where this reflexivity check is key:
Consider trying to prove (f a) ~R (f a). The AppTys in there can't
be decomposed, because representational equality isn't congruent with respect
to AppTy. So, when canonicalising the equality above, we get stuck and
-would normally produce a CIrredEvCan. However, we really do want to
+would normally produce a CIrredCan. However, we really do want to
be able to solve (f a) ~R (f a). So, in the representational case only,
we do a reflexivity check.
@@ -893,16 +1281,15 @@ can_eq_newtype_nc ev swapped ty1 ((gres, co), ty1') ty2 ps_ty2
-- we have actually used the newtype constructor here, so
-- make sure we don't warn about importing it!
- ; rewriteEqEvidence ev swapped ty1' ps_ty2
- (mkTcSymCo co) (mkTcReflCo Representational ps_ty2)
- `andWhenContinue` \ new_ev ->
- can_eq_nc False new_ev ReprEq ty1' ty1' ty2 ps_ty2 }
+ ; new_ev <- rewriteEqEvidence ev swapped ty1' ps_ty2
+ (mkTcSymCo co) (mkTcReflCo Representational ps_ty2)
+ ; can_eq_nc False new_ev ReprEq ty1' ty1' ty2 ps_ty2 }
---------
-- ^ Decompose a type application.
-- All input types must be flat. See Note [Canonicalising type applications]
-can_eq_app :: CtEvidence -- :: s1 t1 ~r s2 t2
- -> EqRel -- r
+-- Nominal equality only!
+can_eq_app :: CtEvidence -- :: s1 t1 ~N s2 t2
-> Xi -> Xi -- s1 t1
-> Xi -> Xi -- s2 t2
-> TcS (StopOrContinue Ct)
@@ -910,34 +1297,46 @@ can_eq_app :: CtEvidence -- :: s1 t1 ~r s2 t2
-- AppTys only decompose for nominal equality, so this case just leads
-- to an irreducible constraint; see typecheck/should_compile/T10494
-- See Note [Decomposing equality], note {4}
-can_eq_app ev ReprEq _ _ _ _
- = do { traceTcS "failing to decompose representational AppTy equality" (ppr ev)
- ; continueWith (CIrredEvCan { cc_ev = ev }) }
- -- no need to call canEqFailure, because that flattens, and the
- -- types involved here are already flat
-
-can_eq_app ev NomEq s1 t1 s2 t2
+can_eq_app ev s1 t1 s2 t2
| CtDerived { ctev_loc = loc } <- ev
= do { unifyDeriveds loc [Nominal, Nominal] [s1, t1] [s2, t2]
; stopWith ev "Decomposed [D] AppTy" }
| CtWanted { ctev_dest = dest, ctev_loc = loc } <- ev
= do { co_s <- unifyWanted loc Nominal s1 s2
- ; co_t <- unifyWanted loc Nominal t1 t2
+ ; let arg_loc
+ | isNextArgVisible s1 = loc
+ | otherwise = updateCtLocOrigin loc toInvisibleOrigin
+ ; co_t <- unifyWanted arg_loc Nominal t1 t2
; let co = mkAppCo co_s co_t
; setWantedEq dest co
; stopWith ev "Decomposed [W] AppTy" }
+
+ -- If there is a ForAll/(->) mismatch, the use of the Left coercion
+ -- below is ill-typed, potentially leading to a panic in splitTyConApp
+ -- Test case: typecheck/should_run/Typeable1
+ -- We could also include this mismatch check above (for W and D), but it's slow
+ -- and we'll get a better error message not doing it
+ | s1k `mismatches` s2k
+ = canEqHardFailure ev (s1 `mkAppTy` t1) (s2 `mkAppTy` t2)
+
| CtGiven { ctev_evar = evar, ctev_loc = loc } <- ev
= do { let co = mkTcCoVarCo evar
co_s = mkTcLRCo CLeft co
co_t = mkTcLRCo CRight co
; evar_s <- newGivenEvVar loc ( mkTcEqPredLikeEv ev s1 s2
- , EvCoercion co_s )
+ , evCoercion co_s )
; evar_t <- newGivenEvVar loc ( mkTcEqPredLikeEv ev t1 t2
- , EvCoercion co_t )
+ , evCoercion co_t )
; emitWorkNC [evar_t]
; canEqNC evar_s NomEq s1 s2 }
- | otherwise -- Can't happen
- = error "can_eq_app"
+
+ where
+ s1k = typeKind s1
+ s2k = typeKind s2
+
+ k1 `mismatches` k2
+ = isForAllTy k1 && not (isForAllTy k2)
+ || not (isForAllTy k1) && isForAllTy k2
-----------------------
-- | Break apart an equality over a casted type
@@ -953,12 +1352,10 @@ canEqCast flat ev eq_rel swapped ty1 co1 ty2 ps_ty2
= do { traceTcS "Decomposing cast" (vcat [ ppr ev
, ppr ty1 <+> text "|>" <+> ppr co1
, ppr ps_ty2 ])
- ; rewriteEqEvidence ev swapped ty1 ps_ty2
- (mkTcReflCo role ty1
- `mkTcCoherenceRightCo` co1)
- (mkTcReflCo role ps_ty2)
- `andWhenContinue` \ new_ev ->
- can_eq_nc flat new_ev eq_rel ty1 ty1 ty2 ps_ty2 }
+ ; new_ev <- rewriteEqEvidence ev swapped ty1 ps_ty2
+ (mkTcGReflRightCo role ty1 co1)
+ (mkTcReflCo role ps_ty2)
+ ; can_eq_nc flat new_ev eq_rel ty1 ty1 ty2 ps_ty2 }
where
role = eqRelRole eq_rel
@@ -982,7 +1379,7 @@ canTyConApp ev eq_rel tc1 tys1 tc2 tys2
-- See Note [Skolem abstract data] (at tyConSkolem)
| tyConSkolem tc1 || tyConSkolem tc2
= do { traceTcS "canTyConApp: skolem abstract" (ppr tc1 $$ ppr tc2)
- ; continueWith (CIrredEvCan { cc_ev = ev }) }
+ ; continueWith (mkIrredCt ev) }
-- Fail straight away for better error messages
-- See Note [Use canEqFailure in canDecomposableTyConApp]
@@ -1203,7 +1600,7 @@ canDecomposableTyConAppOK ev eq_rel tc tys1 tys2
-> do { let ev_co = mkCoVarCo evar
; given_evs <- newGivenEvVars loc $
[ ( mkPrimEqPredRole r ty1 ty2
- , EvCoercion (mkNthCo i ev_co) )
+ , evCoercion $ mkNthCo r i ev_co )
| (r, ty1, ty2, i) <- zip4 tc_roles tys1 tys2 [0..]
, r /= Phantom
, not (isCoercionTy ty1) && not (isCoercionTy ty2) ]
@@ -1216,13 +1613,16 @@ canDecomposableTyConAppOK ev eq_rel tc tys1 tys2
-- the following makes a better distinction between "kind" and "type"
-- in error messages
bndrs = tyConBinders tc
- kind_loc = toKindLoc loc
is_kinds = map isNamedTyConBinder bndrs
- new_locs | Just KindLevel <- ctLocTypeOrKind_maybe loc
- = repeat loc
- | otherwise
- = map (\is_kind -> if is_kind then kind_loc else loc) is_kinds
+ is_viss = map isVisibleTyConBinder bndrs
+
+ kind_xforms = map (\is_kind -> if is_kind then toKindLoc else id) is_kinds
+ vis_xforms = map (\is_vis -> if is_vis then id
+ else flip updateCtLocOrigin toInvisibleOrigin)
+ is_viss
+ -- zipWith3 (.) composes its first two arguments and applies it to the third
+ new_locs = zipWith3 (.) kind_xforms vis_xforms (repeat loc)
-- | Call when canonicalizing an equality fails, but if the equality is
-- representational, there is some hope for the future.
@@ -1239,9 +1639,8 @@ canEqFailure ev ReprEq ty1 ty2
-- new equalities become available
; traceTcS "canEqFailure with ReprEq" $
vcat [ ppr ev, ppr ty1, ppr ty2, ppr xi1, ppr xi2 ]
- ; rewriteEqEvidence ev NotSwapped xi1 xi2 co1 co2
- `andWhenContinue` \ new_ev ->
- continueWith (CIrredEvCan { cc_ev = new_ev }) }
+ ; new_ev <- rewriteEqEvidence ev NotSwapped xi1 xi2 co1 co2
+ ; continueWith (mkIrredCt new_ev) }
-- | Call when canonicalizing an equality fails with utterly no hope.
canEqHardFailure :: CtEvidence
@@ -1250,10 +1649,8 @@ canEqHardFailure :: CtEvidence
canEqHardFailure ev ty1 ty2
= do { (s1, co1) <- flatten FM_SubstOnly ev ty1
; (s2, co2) <- flatten FM_SubstOnly ev ty2
- ; rewriteEqEvidence ev NotSwapped s1 s2 co1 co2
- `andWhenContinue` \ new_ev ->
- do { emitInsoluble (mkNonCanonical new_ev)
- ; stopWith new_ev "Definitely not equal" }}
+ ; new_ev <- rewriteEqEvidence ev NotSwapped s1 s2 co1 co2
+ ; continueWith (mkInsolubleCt new_ev) }
{-
Note [Decomposing TyConApps]
@@ -1356,19 +1753,25 @@ isInsolubleOccursCheck does.
See also #10715, which induced this addition.
-Note [No derived kind equalities]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When we're working with a heterogeneous derived equality
-
- [D] (t1 :: k1) ~ (t2 :: k2)
-
-we want to homogenise to establish the kind invariant on CTyEqCans.
-But we can't emit [D] k1 ~ k2 because we wouldn't then be able to
-use the evidence in the homogenised types. So we emit a wanted
-constraint, because we do really need the evidence here.
-
-Thus: no derived kind equalities.
-
+Note [canCFunEqCan]
+~~~~~~~~~~~~~~~~~~~
+Flattening the arguments to a type family can change the kind of the type
+family application. As an easy example, consider (Any k) where (k ~ Type)
+is in the inert set. The original (Any k :: k) becomes (Any Type :: Type).
+The problem here is that the fsk in the CFunEqCan will have the old kind.
+
+The solution is to come up with a new fsk/fmv of the right kind. For
+givens, this is easy: just introduce a new fsk and update the flat-cache
+with the new one. For wanteds, we want to solve the old one if favor of
+the new one, so we use dischargeFmv. This also kicks out constraints
+from the inert set; this behavior is correct, as the kind-change may
+allow more constraints to be solved.
+
+We use `isTcReflexiveCo`, to ensure that we only use the hetero-kinded case
+if we really need to. Of course `flattenArgsNom` should return `Refl`
+whenever possible, but Trac #15577 was an infinite loop because even
+though the coercion was homo-kinded, `kind_co` was not `Refl`, so we
+made a new (identical) CFunEqCan, and then the entire process repeated.
-}
canCFunEqCan :: CtEvidence
@@ -1380,90 +1783,254 @@ canCFunEqCan :: CtEvidence
-- and the RHS is a fsk, which we must *not* substitute.
-- So just substitute in the LHS
canCFunEqCan ev fn tys fsk
- = do { (tys', cos) <- flattenManyNom ev tys
+ = do { (tys', cos, kind_co) <- flattenArgsNom ev fn tys
-- cos :: tys' ~ tys
; let lhs_co = mkTcTyConAppCo Nominal fn cos
-- :: F tys' ~ F tys
new_lhs = mkTyConApp fn tys'
- fsk_ty = mkTyVarTy fsk
- ; rewriteEqEvidence ev NotSwapped new_lhs fsk_ty
- lhs_co (mkTcNomReflCo fsk_ty)
- `andWhenContinue` \ ev' ->
- do { extendFlatCache fn tys' (ctEvCoercion ev', fsk_ty, ctEvFlavour ev')
+
+ flav = ctEvFlavour ev
+ ; (ev', fsk')
+ <- if isTcReflexiveCo kind_co -- See Note [canCFunEqCan]
+ then do { traceTcS "canCFunEqCan: refl" (ppr new_lhs $$ ppr lhs_co)
+ ; let fsk_ty = mkTyVarTy fsk
+ ; ev' <- rewriteEqEvidence ev NotSwapped new_lhs fsk_ty
+ lhs_co (mkTcNomReflCo fsk_ty)
+ ; return (ev', fsk) }
+ else do { traceTcS "canCFunEqCan: non-refl" $
+ vcat [ text "Kind co:" <+> ppr kind_co
+ , text "RHS:" <+> ppr fsk <+> dcolon <+> ppr (tyVarKind fsk)
+ , text "LHS:" <+> hang (ppr (mkTyConApp fn tys))
+ 2 (dcolon <+> ppr (typeKind (mkTyConApp fn tys)))
+ , text "New LHS" <+> hang (ppr new_lhs)
+ 2 (dcolon <+> ppr (typeKind new_lhs)) ]
+ ; (ev', new_co, new_fsk)
+ <- newFlattenSkolem flav (ctEvLoc ev) fn tys'
+ ; let xi = mkTyVarTy new_fsk `mkCastTy` kind_co
+ -- sym lhs_co :: F tys ~ F tys'
+ -- new_co :: F tys' ~ new_fsk
+ -- co :: F tys ~ (new_fsk |> kind_co)
+ co = mkTcSymCo lhs_co `mkTcTransCo`
+ mkTcCoherenceRightCo Nominal
+ (mkTyVarTy new_fsk)
+ kind_co
+ new_co
+
+ ; traceTcS "Discharging fmv/fsk due to hetero flattening" (ppr ev)
+ ; dischargeFunEq ev fsk co xi
+ ; return (ev', new_fsk) }
+
+ ; extendFlatCache fn tys' (ctEvCoercion ev', mkTyVarTy fsk', ctEvFlavour ev')
; continueWith (CFunEqCan { cc_ev = ev', cc_fun = fn
- , cc_tyargs = tys', cc_fsk = fsk }) } }
+ , cc_tyargs = tys', cc_fsk = fsk' }) }
---------------------
canEqTyVar :: CtEvidence -- ev :: lhs ~ rhs
-> EqRel -> SwapFlag
- -> TcTyVar -> TcType -- lhs: already flat, not a cast
- -> TcType -> TcType -- rhs: already flat, not a cast
+ -> TcTyVar -- tv1
+ -> TcType -- lhs: pretty lhs, already flat
+ -> TcType -> TcType -- rhs: already flat
-> TcS (StopOrContinue Ct)
-canEqTyVar ev eq_rel swapped tv1 ps_ty1 (TyVarTy tv2) _
- | tv1 == tv2
- = canEqReflexive ev eq_rel ps_ty1
+canEqTyVar ev eq_rel swapped tv1 ps_ty1 xi2 ps_xi2
+ | k1 `tcEqType` k2
+ = canEqTyVarHomo ev eq_rel swapped tv1 ps_ty1 xi2 ps_xi2
- | swapOverTyVars tv1 tv2
- = do { traceTcS "canEqTyVar" (ppr tv1 $$ ppr tv2 $$ ppr swapped)
+ -- Note [Flattening] in TcFlatten gives us (F2), which says that
+ -- flattening is always homogeneous (doesn't change kinds). But
+ -- perhaps by flattening the kinds of the two sides of the equality
+ -- at hand makes them equal. So let's try that.
+ | otherwise
+ = do { (flat_k1, k1_co) <- flattenKind loc flav k1 -- k1_co :: flat_k1 ~N kind(xi1)
+ ; (flat_k2, k2_co) <- flattenKind loc flav k2 -- k2_co :: flat_k2 ~N kind(xi2)
+ ; traceTcS "canEqTyVar tried flattening kinds"
+ (vcat [ sep [ parens (ppr tv1 <+> dcolon <+> ppr k1)
+ , text "~"
+ , parens (ppr xi2 <+> dcolon <+> ppr k2) ]
+ , ppr flat_k1
+ , ppr k1_co
+ , ppr flat_k2
+ , ppr k2_co ])
+
+ -- we know the LHS is a tyvar. So let's dump all the coercions on the RHS
+ -- If flat_k1 == flat_k2, let's dump all the coercions on the RHS and
+ -- then call canEqTyVarHomo. If they don't equal, just rewriteEqEvidence
+ -- (as an optimization, so that we don't have to flatten the kinds again)
+ -- and then emit a kind equality in canEqTyVarHetero.
+ -- See Note [Equalities with incompatible kinds]
+
+ ; let role = eqRelRole eq_rel
+ ; if flat_k1 `tcEqType` flat_k2
+ then do { let rhs_kind_co = mkTcSymCo k2_co `mkTcTransCo` k1_co
+ -- :: kind(xi2) ~N kind(xi1)
+
+ new_rhs = xi2 `mkCastTy` rhs_kind_co
+ ps_rhs = ps_xi2 `mkCastTy` rhs_kind_co
+ rhs_co = mkTcGReflLeftCo role xi2 rhs_kind_co
+
+ ; new_ev <- rewriteEqEvidence ev swapped xi1 new_rhs
+ (mkTcReflCo role xi1) rhs_co
+ -- NB: rewriteEqEvidence executes a swap, if any, so we're
+ -- NotSwapped now.
+ ; canEqTyVarHomo new_ev eq_rel NotSwapped tv1 ps_ty1 new_rhs ps_rhs }
+ else
+ do { let sym_k1_co = mkTcSymCo k1_co -- :: kind(xi1) ~N flat_k1
+ sym_k2_co = mkTcSymCo k2_co -- :: kind(xi2) ~N flat_k2
+
+ new_lhs = xi1 `mkCastTy` sym_k1_co -- :: flat_k1
+ new_rhs = xi2 `mkCastTy` sym_k2_co -- :: flat_k2
+ ps_rhs = ps_xi2 `mkCastTy` sym_k2_co
+
+ lhs_co = mkTcGReflLeftCo role xi1 sym_k1_co
+ rhs_co = mkTcGReflLeftCo role xi2 sym_k2_co
+ -- lhs_co :: (xi1 |> sym k1_co) ~ xi1
+ -- rhs_co :: (xi2 |> sym k2_co) ~ xi2
+
+ ; new_ev <- rewriteEqEvidence ev swapped new_lhs new_rhs lhs_co rhs_co
+ -- no longer swapped, due to rewriteEqEvidence
+ ; canEqTyVarHetero new_ev eq_rel tv1 sym_k1_co flat_k1 ps_ty1
+ new_rhs flat_k2 ps_rhs } }
+ where
+ xi1 = mkTyVarTy tv1
+
+ k1 = tyVarKind tv1
+ k2 = typeKind xi2
+
+ loc = ctEvLoc ev
+ flav = ctEvFlavour ev
+
+canEqTyVarHetero :: CtEvidence -- :: (tv1 |> co1 :: ki1) ~ (xi2 :: ki2)
+ -> EqRel
+ -> TcTyVar -> TcCoercionN -> TcKind -- tv1 |> co1 :: ki1
+ -> TcType -- pretty tv1 (*without* the coercion)
+ -> TcType -> TcKind -- xi2 :: ki2
+ -> TcType -- pretty xi2
+ -> TcS (StopOrContinue Ct)
+canEqTyVarHetero ev eq_rel tv1 co1 ki1 ps_tv1 xi2 ki2 ps_xi2
+ -- See Note [Equalities with incompatible kinds]
+ | CtGiven { ctev_evar = evar } <- ev
+ -- unswapped: tm :: (lhs :: ki1) ~ (rhs :: ki2)
+ -- swapped : tm :: (rhs :: ki2) ~ (lhs :: ki1)
+ = do { let kind_co = mkTcKindCo (mkTcCoVarCo evar)
+ ; kind_ev <- newGivenEvVar kind_loc (kind_pty, evCoercion kind_co)
+ ; let -- kind_ev :: (ki1 :: *) ~ (ki2 :: *) (whether swapped or not)
+ -- co1 :: kind(tv1) ~N ki1
+ -- homo_co :: ki2 ~N kind(tv1)
+ homo_co = mkTcSymCo (ctEvCoercion kind_ev) `mkTcTransCo` mkTcSymCo co1
+ rhs' = mkCastTy xi2 homo_co -- :: kind(tv1)
+ ps_rhs' = mkCastTy ps_xi2 homo_co -- :: kind(tv1)
+ rhs_co = mkTcGReflLeftCo role xi2 homo_co
+ -- rhs_co :: (xi2 |> homo_co :: kind(tv1)) ~ xi2
+
+ lhs' = mkTyVarTy tv1 -- :: kind(tv1)
+ lhs_co = mkTcGReflRightCo role lhs' co1
+ -- lhs_co :: (tv1 :: kind(tv1)) ~ (tv1 |> co1 :: ki1)
+
+ ; traceTcS "Hetero equality gives rise to given kind equality"
+ (ppr kind_ev <+> dcolon <+> ppr kind_pty)
+ ; emitWorkNC [kind_ev]
+ ; type_ev <- rewriteEqEvidence ev NotSwapped lhs' rhs' lhs_co rhs_co
+ ; canEqTyVarHomo type_ev eq_rel NotSwapped tv1 ps_tv1 rhs' ps_rhs' }
+
+ -- See Note [Equalities with incompatible kinds]
+ | otherwise -- Wanted and Derived
+ -- NB: all kind equalities are Nominal
+ = do { emitNewDerivedEq kind_loc Nominal ki1 ki2
+ -- kind_ev :: (ki1 :: *) ~ (ki2 :: *)
+ ; traceTcS "Hetero equality gives rise to derived kind equality" $
+ ppr ev
+ ; continueWith (mkIrredCt ev) }
+
+ where
+ kind_pty = mkHeteroPrimEqPred liftedTypeKind liftedTypeKind ki1 ki2
+ kind_loc = mkKindLoc (mkTyVarTy tv1 `mkCastTy` co1) xi2 loc
+
+ loc = ctev_loc ev
+ role = eqRelRole eq_rel
+
+-- guaranteed that typeKind lhs == typeKind rhs
+canEqTyVarHomo :: CtEvidence
+ -> EqRel -> SwapFlag
+ -> TcTyVar -- lhs: tv1
+ -> TcType -- pretty lhs
+ -> TcType -> TcType -- rhs (might not be flat)
+ -> TcS (StopOrContinue Ct)
+canEqTyVarHomo ev eq_rel swapped tv1 ps_ty1 ty2 _
+ | Just (tv2, _) <- tcGetCastedTyVar_maybe ty2
+ , tv1 == tv2
+ = canEqReflexive ev eq_rel (mkTyVarTy tv1)
+ -- we don't need to check co because it must be reflexive
+
+ | Just (tv2, co2) <- tcGetCastedTyVar_maybe ty2
+ , swapOverTyVars tv1 tv2
+ = do { traceTcS "canEqTyVar swapOver" (ppr tv1 $$ ppr tv2 $$ ppr swapped)
-- FM_Avoid commented out: see Note [Lazy flattening] in TcFlatten
-- let fmode = FE { fe_ev = ev, fe_mode = FM_Avoid tv1' True }
-- Flatten the RHS less vigorously, to avoid gratuitous flattening
-- True <=> xi2 should not itself be a type-function application
+
+ ; let role = eqRelRole eq_rel
+ sym_co2 = mkTcSymCo co2
+ ty1 = mkTyVarTy tv1
+ new_lhs = ty1 `mkCastTy` sym_co2
+ lhs_co = mkTcGReflLeftCo role ty1 sym_co2
+
+ new_rhs = mkTyVarTy tv2
+ rhs_co = mkTcGReflRightCo role new_rhs co2
+
+ ; new_ev <- rewriteEqEvidence ev swapped new_lhs new_rhs lhs_co rhs_co
+
; dflags <- getDynFlags
- ; canEqTyVar2 dflags ev eq_rel (flipSwap swapped) tv2 ps_ty1 }
+ ; canEqTyVar2 dflags new_ev eq_rel IsSwapped tv2 (ps_ty1 `mkCastTy` sym_co2) }
-canEqTyVar ev eq_rel swapped tv1 _ _ ps_ty2
+canEqTyVarHomo ev eq_rel swapped tv1 _ _ ps_ty2
= do { dflags <- getDynFlags
; canEqTyVar2 dflags ev eq_rel swapped tv1 ps_ty2 }
+-- The RHS here is either not a casted tyvar, or it's a tyvar but we want
+-- to rewrite the LHS to the RHS (as per swapOverTyVars)
canEqTyVar2 :: DynFlags
-> CtEvidence -- lhs ~ rhs (or, if swapped, orhs ~ olhs)
-> EqRel
-> SwapFlag
- -> TcTyVar -- lhs, flat
- -> TcType -- rhs, flat
+ -> TcTyVar -- lhs = tv, flat
+ -> TcType -- rhs
-> TcS (StopOrContinue Ct)
-- LHS is an inert type variable,
-- and RHS is fully rewritten, but with type synonyms
-- preserved as much as possible
-
-canEqTyVar2 dflags ev eq_rel swapped tv1 xi2
- | Just xi2' <- metaTyVarUpdateOK dflags tv1 xi2 -- No occurs check
+canEqTyVar2 dflags ev eq_rel swapped tv1 rhs
+ | Just rhs' <- metaTyVarUpdateOK dflags tv1 rhs -- No occurs check
-- Must do the occurs check even on tyvar/tyvar
-- equalities, in case have x ~ (y :: ..x...)
-- Trac #12593
- = rewriteEqEvidence ev swapped xi1 xi2' co1 co2
- `andWhenContinue` \ new_ev ->
- homogeniseRhsKind new_ev eq_rel xi1 xi2' $ \new_new_ev xi2'' ->
- CTyEqCan { cc_ev = new_new_ev, cc_tyvar = tv1
- , cc_rhs = xi2'', cc_eq_rel = eq_rel }
+ = do { new_ev <- rewriteEqEvidence ev swapped lhs rhs' rewrite_co1 rewrite_co2
+ ; continueWith (CTyEqCan { cc_ev = new_ev, cc_tyvar = tv1
+ , cc_rhs = rhs', cc_eq_rel = eq_rel }) }
| otherwise -- For some reason (occurs check, or forall) we can't unify
-- We must not use it for further rewriting!
- = do { traceTcS "canEqTyVar2 can't unify" (ppr tv1 $$ ppr xi2)
- ; rewriteEqEvidence ev swapped xi1 xi2 co1 co2
- `andWhenContinue` \ new_ev ->
- if isInsolubleOccursCheck eq_rel tv1 xi2
- then do { emitInsoluble (mkNonCanonical new_ev)
+ = do { traceTcS "canEqTyVar2 can't unify" (ppr tv1 $$ ppr rhs)
+ ; new_ev <- rewriteEqEvidence ev swapped lhs rhs rewrite_co1 rewrite_co2
+ ; if isInsolubleOccursCheck eq_rel tv1 rhs
+ then continueWith (mkInsolubleCt new_ev)
-- If we have a ~ [a], it is not canonical, and in particular
-- we don't want to rewrite existing inerts with it, otherwise
-- we'd risk divergence in the constraint solver
- ; stopWith new_ev "Occurs check" }
+ else continueWith (mkIrredCt new_ev) }
-- A representational equality with an occurs-check problem isn't
-- insoluble! For example:
-- a ~R b a
-- We might learn that b is the newtype Id.
-- But, the occurs-check certainly prevents the equality from being
-- canonical, and we might loop if we were to use it in rewriting.
- else do { traceTcS "Possibly-soluble occurs check"
- (ppr xi1 $$ ppr xi2)
- ; continueWith (CIrredEvCan { cc_ev = new_ev }) } }
where
role = eqRelRole eq_rel
- xi1 = mkTyVarTy tv1
- co1 = mkTcReflCo role xi1
- co2 = mkTcReflCo role xi2
+
+ lhs = mkTyVarTy tv1
+
+ rewrite_co1 = mkTcReflCo role lhs
+ rewrite_co2 = mkTcReflCo role rhs
-- | Solve a reflexive equality constraint
canEqReflexive :: CtEvidence -- ty ~ ty
@@ -1471,79 +2038,10 @@ canEqReflexive :: CtEvidence -- ty ~ ty
-> TcType -- ty
-> TcS (StopOrContinue Ct) -- always Stop
canEqReflexive ev eq_rel ty
- = do { setEvBindIfWanted ev (EvCoercion $
+ = do { setEvBindIfWanted ev (evCoercion $
mkTcReflCo (eqRelRole eq_rel) ty)
; stopWith ev "Solved by reflexivity" }
--- See Note [Equalities with incompatible kinds]
-homogeniseRhsKind :: CtEvidence -- ^ the evidence to homogenise
- -> EqRel
- -> TcType -- ^ original LHS
- -> Xi -- ^ original RHS
- -> (CtEvidence -> Xi -> Ct)
- -- ^ how to build the homogenised constraint;
- -- the 'Xi' is the new RHS
- -> TcS (StopOrContinue Ct)
-homogeniseRhsKind ev eq_rel lhs rhs build_ct
- | k1 `tcEqType` k2
- = continueWith (build_ct ev rhs)
-
- | CtGiven { ctev_evar = evar } <- ev
- -- tm :: (lhs :: k1) ~ (rhs :: k2)
- = do { kind_ev_id <- newBoundEvVarId kind_pty
- (EvCoercion $
- mkTcKindCo $ mkTcCoVarCo evar)
- -- kind_ev_id :: (k1 :: *) ~# (k2 :: *)
- ; let kind_ev = CtGiven { ctev_pred = kind_pty
- , ctev_evar = kind_ev_id
- , ctev_loc = kind_loc }
- homo_co = mkSymCo $ mkCoVarCo kind_ev_id
- rhs' = mkCastTy rhs homo_co
- ; traceTcS "Hetero equality gives rise to given kind equality"
- (ppr kind_ev_id <+> dcolon <+> ppr kind_pty)
- ; emitWorkNC [kind_ev]
- ; type_ev <- newGivenEvVar loc
- ( mkTcEqPredLikeEv ev lhs rhs'
- , EvCoercion $
- mkTcCoherenceRightCo (mkTcCoVarCo evar) homo_co )
- -- type_ev :: (lhs :: k1) ~ ((rhs |> sym kind_ev_id) :: k1)
- ; continueWith (build_ct type_ev rhs') }
-
- | otherwise -- Wanted and Derived. See Note [No derived kind equalities]
- -- evar :: (lhs :: k1) ~ (rhs :: k2)
- = do { kind_co <- emitNewWantedEq kind_loc Nominal k1 k2
- -- kind_ev :: (k1 :: *) ~ (k2 :: *)
- ; traceTcS "Hetero equality gives rise to wanted kind equality" $
- ppr (kind_co)
- ; let homo_co = mkSymCo kind_co
- -- homo_co :: k2 ~ k1
- rhs' = mkCastTy rhs homo_co
- ; case ev of
- CtGiven {} -> panic "homogeniseRhsKind"
- CtDerived {} -> continueWith (build_ct (ev { ctev_pred = homo_pred })
- rhs')
- where homo_pred = mkTcEqPredLikeEv ev lhs rhs'
- CtWanted { ctev_dest = dest } -> do
- { (type_ev, hole_co) <- newWantedEq loc role lhs rhs'
- -- type_ev :: (lhs :: k1) ~ (rhs |> sym kind_co :: k1)
- ; setWantedEq dest
- (hole_co `mkTransCo`
- (mkReflCo role rhs
- `mkCoherenceLeftCo` homo_co))
-
- -- dest := hole ; <rhs> |> homo_co :: (lhs :: k1) ~ (rhs :: k2)
- ; continueWith (build_ct type_ev rhs') }}
-
- where
- k1 = typeKind lhs
- k2 = typeKind rhs
-
- kind_pty = mkHeteroPrimEqPred liftedTypeKind liftedTypeKind k1 k2
- kind_loc = mkKindLoc lhs rhs loc
-
- loc = ctev_loc ev
- role = eqRelRole eq_rel
-
{-
Note [Canonical orientation for tyvar/tyvar equality constraints]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1560,66 +2058,85 @@ canEqTyVarTyVar, are these
number) on the left, so there is the best chance of unifying it
alpha[3] ~ beta[2]
- * If both are meta-tyvars and both at the same level, put a SigTv
+ * If both are meta-tyvars and both at the same level, put a TyVarTv
on the right if possible
alpha[2] ~ beta[2](sig-tv)
- That way, when we unify alpha := beta, we don't lose the SigTv flag.
+ That way, when we unify alpha := beta, we don't lose the TyVarTv flag.
* Put a meta-tv with a System Name on the left if possible so it
gets eliminated (improves error messages)
* If one is a flatten-skolem, put it on the left so that it is
- substituted out Note [Elminate flat-skols]
+ substituted out Note [Eliminate flat-skols] in TcUinfy
fsk ~ a
-Note [Avoid unnecessary swaps]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-If we swap without actually improving matters, we can get an infnite loop.
-Consider
- work item: a ~ b
- inert item: b ~ c
-We canonicalise the work-time to (a ~ c). If we then swap it before
-aeding to the inert set, we'll add (c ~ a), and therefore kick out the
-inert guy, so we get
- new work item: b ~ c
- inert item: c ~ a
-And now the cycle just repeats
-
-Note [Eliminate flat-skols]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Suppose we have [G] Num (F [a])
-then we flatten to
- [G] Num fsk
- [G] F [a] ~ fsk
-where fsk is a flatten-skolem (FlatSkolTv). Suppose we have
- type instance F [a] = a
-then we'll reduce the second constraint to
- [G] a ~ fsk
-and then replace all uses of 'a' with fsk. That's bad because
-in error messages intead of saying 'a' we'll say (F [a]). In all
-places, including those where the programmer wrote 'a' in the first
-place. Very confusing! See Trac #7862.
-
-Solution: re-orient a~fsk to fsk~a, so that we preferentially eliminate
-the fsk.
-
Note [Equalities with incompatible kinds]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-canEqLeaf is about to make a CTyEqCan or CFunEqCan; but both have the
-invariant that LHS and RHS satisfy the kind invariants for CTyEqCan,
-CFunEqCan. What if we try to unify two things with incompatible
-kinds?
+What do we do when we have an equality
+
+ (tv :: k1) ~ (rhs :: k2)
+
+where k1 and k2 differ? This Note explores this treacherous area.
+
+First off, the question above is slightly the wrong question. Flattening
+a tyvar will flatten its kind (Note [Flattening] in TcFlatten); flattening
+the kind might introduce a cast. So we might have a casted tyvar on the
+left. We thus revise our test case to
+
+ (tv |> co :: k1) ~ (rhs :: k2)
+
+We must proceed differently here depending on whether we have a Wanted
+or a Given. Consider this:
-eg a ~ b where a::*, b::*->*
-or a ~ b where a::*, b::k, k is a kind variable
+ [W] w :: (alpha :: k) ~ (Int :: Type)
-The CTyEqCan compatKind invariant is important. If we make a CTyEqCan
-for a~b, then we might well *substitute* 'b' for 'a', and that might make
-a well-kinded type ill-kinded; and that is bad (eg typeKind can crash, see
-Trac #7696).
+where k is a skolem. One possible way forward is this:
-So instead for these ill-kinded equalities we homogenise the RHS of the
-equality, emitting new constraints as necessary.
+ [W] co :: k ~ Type
+ [W] w :: (alpha :: k) ~ (Int |> sym co :: k)
+
+The next step will be to unify
+
+ alpha := Int |> sym co
+
+Now, consider what error we'll report if we can't solve the "co"
+wanted. Its CtOrigin is the w wanted... which now reads (after zonking)
+Int ~ Int. The user thus sees that GHC can't solve Int ~ Int, which
+is embarrassing. See #11198 for more tales of destruction.
+
+The reason for this odd behavior is much the same as
+Note [Wanteds do not rewrite Wanteds] in TcRnTypes: note that the
+new `co` is a Wanted.
+
+ The solution is then not to use `co` to "rewrite" -- that is, cast
+ -- `w`, but instead to keep `w` heterogeneous and
+ irreducible. Given that we're not using `co`, there is no reason to
+ collect evidence for it, so `co` is born a Derived, with a CtOrigin
+ of KindEqOrigin.
+
+When the Derived is solved (by unification), the original wanted (`w`)
+will get kicked out.
+
+Note that, if we had [G] co1 :: k ~ Type available, then none of this code would
+trigger, because flattening would have rewritten k to Type. That is,
+`w` would look like [W] (alpha |> co1 :: Type) ~ (Int :: Type), and the tyvar
+case will trigger, correctly rewriting alpha to (Int |> sym co1).
+
+Successive canonicalizations of the same Wanted may produce
+duplicate Deriveds. Similar duplications can happen with fundeps, and there
+seems to be no easy way to avoid. I expect this case to be rare.
+
+For Givens, this problem doesn't bite, so a heterogeneous Given gives
+rise to a Given kind equality. No Deriveds here. We thus homogenise
+the Given (see the "homo_co" in the Given case in canEqTyVar) and
+carry on with a homogeneous equality constraint.
+
+Separately, I (Richard E) spent some time pondering what to do in the case
+that we have [W] (tv |> co1 :: k1) ~ (tv |> co2 :: k2) where k1 and k2
+differ. Note that the tv is the same. (This case is handled as the first
+case in canEqTyVarHomo.) At one point, I thought we could solve this limited
+form of heterogeneous Wanted, but I then reconsidered and now treat this case
+just like any other heterogeneous Wanted.
Note [Type synonyms and canonicalization]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1749,7 +2266,7 @@ rewriteEvidence old_ev@(CtDerived {}) new_pred _co
-- rewriteEvidence to put the isTcReflCo test first!
-- Why? Because for *Derived* constraints, c, the coercion, which
-- was produced by flattening, may contain suspended calls to
- -- (ctEvTerm c), which fails for Derived constraints.
+ -- (ctEvExpr c), which fails for Derived constraints.
-- (Getting this wrong caused Trac #7384.)
continueWith (old_ev { ctev_pred = new_pred })
@@ -1757,12 +2274,12 @@ rewriteEvidence old_ev new_pred co
| isTcReflCo co -- See Note [Rewriting with Refl]
= continueWith (old_ev { ctev_pred = new_pred })
-rewriteEvidence ev@(CtGiven { ctev_evar = old_evar , ctev_loc = loc }) new_pred co
+rewriteEvidence ev@(CtGiven { ctev_evar = old_evar, ctev_loc = loc }) new_pred co
= do { new_ev <- newGivenEvVar loc (new_pred, new_tm)
; continueWith new_ev }
where
-- mkEvCast optimises ReflCo
- new_tm = mkEvCast (EvId old_evar) (tcDowngradeRole Representational
+ new_tm = mkEvCast (evId old_evar) (tcDowngradeRole Representational
(ctEvRole ev)
(mkTcSymCo co))
@@ -1771,8 +2288,8 @@ rewriteEvidence ev@(CtWanted { ctev_dest = dest
= do { mb_new_ev <- newWanted loc new_pred
; MASSERT( tcCoercionRole co == ctEvRole ev )
; setWantedEvTerm dest
- (mkEvCast (getEvTerm mb_new_ev)
- (tcDowngradeRole Representational (ctEvRole ev) co))
+ (mkEvCast (getEvExpr mb_new_ev)
+ (tcDowngradeRole Representational (ctEvRole ev) co))
; case mb_new_ev of
Fresh new_ev -> continueWith new_ev
Cached _ -> stopWith ev "Cached wanted" }
@@ -1785,7 +2302,7 @@ rewriteEqEvidence :: CtEvidence -- Old evidence :: olhs ~ orhs (not swap
-- Should be zonked, because we use typeKind on nlhs/nrhs
-> TcCoercion -- lhs_co, of type :: nlhs ~ olhs
-> TcCoercion -- rhs_co, of type :: nrhs ~ orhs
- -> TcS (StopOrContinue CtEvidence) -- Of type nlhs ~ nrhs
+ -> TcS CtEvidence -- Of type nlhs ~ nrhs
-- For (rewriteEqEvidence (Given g olhs orhs) False nlhs nrhs lhs_co rhs_co)
-- we generate
-- If not swapped
@@ -1803,19 +2320,18 @@ rewriteEqEvidence :: CtEvidence -- Old evidence :: olhs ~ orhs (not swap
-- It's all a form of rewwriteEvidence, specialised for equalities
rewriteEqEvidence old_ev swapped nlhs nrhs lhs_co rhs_co
| CtDerived {} <- old_ev -- Don't force the evidence for a Derived
- = continueWith (old_ev { ctev_pred = new_pred })
+ = return (old_ev { ctev_pred = new_pred })
| NotSwapped <- swapped
, isTcReflCo lhs_co -- See Note [Rewriting with Refl]
, isTcReflCo rhs_co
- = continueWith (old_ev { ctev_pred = new_pred })
+ = return (old_ev { ctev_pred = new_pred })
| CtGiven { ctev_evar = old_evar } <- old_ev
- = do { let new_tm = EvCoercion (lhs_co
+ = do { let new_tm = evCoercion (lhs_co
`mkTcTransCo` maybeSym swapped (mkTcCoVarCo old_evar)
`mkTcTransCo` mkTcSymCo rhs_co)
- ; new_ev <- newGivenEvVar loc' (new_pred, new_tm)
- ; continueWith new_ev }
+ ; newGivenEvVar loc' (new_pred, new_tm) }
| CtWanted { ctev_dest = dest } <- old_ev
= do { (new_ev, hole_co) <- newWantedEq loc' (ctEvRole old_ev) nlhs nrhs
@@ -1825,7 +2341,7 @@ rewriteEqEvidence old_ev swapped nlhs nrhs lhs_co rhs_co
`mkTransCo` rhs_co
; setWantedEq dest co
; traceTcS "rewriteEqEvidence" (vcat [ppr old_ev, ppr nlhs, ppr nrhs, ppr co])
- ; continueWith new_ev }
+ ; return new_ev }
| otherwise
= panic "rewriteEvidence"
@@ -1845,7 +2361,7 @@ When decomposing equalities we often create new wanted constraints for
Similar remarks apply for Derived.
Rather than making an equality test (which traverses the structure of the
-type, perhaps fruitlessly, unifyWanted traverses the common structure, and
+type, perhaps fruitlessly), unifyWanted traverses the common structure, and
bales out when it finds a difference by creating a new Wanted constraint.
But where it succeeds in finding common structure, it just builds a coercion
to reflect it.