summaryrefslogtreecommitdiff
path: root/compiler/GHC/Tc/Utils/TcMType.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/Tc/Utils/TcMType.hs')
-rw-r--r--compiler/GHC/Tc/Utils/TcMType.hs172
1 files changed, 129 insertions, 43 deletions
diff --git a/compiler/GHC/Tc/Utils/TcMType.hs b/compiler/GHC/Tc/Utils/TcMType.hs
index 1ece974166..3c978b511c 100644
--- a/compiler/GHC/Tc/Utils/TcMType.hs
+++ b/compiler/GHC/Tc/Utils/TcMType.hs
@@ -37,9 +37,9 @@ module GHC.Tc.Utils.TcMType (
--------------------------------
-- Creating new evidence variables
newEvVar, newEvVars, newDict,
- newWantedWithLoc, newWanted, newWanteds, cloneWanted, cloneWC,
+ newWantedWithLoc, newWanted, newWanteds, cloneWanted, cloneWC, cloneWantedCtEv,
emitWanted, emitWantedEq, emitWantedEvVar, emitWantedEvVars,
- emitDerivedEqs,
+ emitWantedEqs,
newTcEvBinds, newNoTcEvBinds, addTcEvBind,
emitNewExprHole,
@@ -47,6 +47,8 @@ module GHC.Tc.Utils.TcMType (
unpackCoercionHole, unpackCoercionHole_maybe,
checkCoercionHole,
+ ConcreteHole, newConcreteHole,
+
newImplication,
--------------------------------
@@ -97,6 +99,10 @@ module GHC.Tc.Utils.TcMType (
------------------------------
-- Representation polymorphism
checkTypeHasFixedRuntimeRep,
+
+ ------------------------------
+ -- Other
+ anyUnfilledCoercionHoles
) where
import GHC.Prelude
@@ -192,12 +198,15 @@ newEvVar ty = do { name <- newSysName (predTypeOccName ty)
-- | Create a new Wanted constraint with the given 'CtLoc'.
newWantedWithLoc :: CtLoc -> PredType -> TcM CtEvidence
newWantedWithLoc loc pty
- = do d <- if isEqPrimPred pty then HoleDest <$> newCoercionHole pty
- else EvVarDest <$> newEvVar pty
- return $ CtWanted { ctev_dest = d
- , ctev_pred = pty
- , ctev_nosh = WDeriv
- , ctev_loc = loc }
+ = do d <- case classifyPredType pty of
+ EqPred {} -> HoleDest <$> newCoercionHole pty
+ SpecialPred ConcretePrimPred ty ->
+ HoleDest <$> (fst <$> newConcreteHole (typeKind ty) ty)
+ _ -> EvVarDest <$> newEvVar pty
+ return $ CtWanted { ctev_dest = d
+ , ctev_pred = pty
+ , ctev_loc = loc
+ , ctev_rewriters = emptyRewriterSet }
-- | Create a new Wanted constraint with the given 'CtOrigin', and
-- location information taken from the 'TcM' environment.
@@ -216,13 +225,20 @@ newWanteds orig = mapM (newWanted orig Nothing)
-- Cloning constraints
----------------------------------------------
-cloneWanted :: Ct -> TcM Ct
-cloneWanted ct
- | ev@(CtWanted { ctev_pred = pty, ctev_dest = HoleDest _ }) <- ctEvidence ct
+cloneWantedCtEv :: CtEvidence -> TcM CtEvidence
+cloneWantedCtEv ctev@(CtWanted { ctev_pred = pty, ctev_dest = HoleDest _ })
+ | isEqPrimPred pty
= do { co_hole <- newCoercionHole pty
- ; return (mkNonCanonical (ev { ctev_dest = HoleDest co_hole })) }
+ ; return (ctev { ctev_dest = HoleDest co_hole }) }
+ | SpecialPred ConcretePrimPred ty <- classifyPredType pty
+ = do { (co_hole, _) <- newConcreteHole (typeKind ty) ty
+ ; return (ctev { ctev_dest = HoleDest co_hole }) }
| otherwise
- = return ct
+ = pprPanic "cloneWantedCtEv" (ppr pty)
+cloneWantedCtEv ctev = return ctev
+
+cloneWanted :: Ct -> TcM Ct
+cloneWanted ct = mkNonCanonical <$> cloneWantedCtEv (ctEvidence ct)
cloneWC :: WantedConstraints -> TcM WantedConstraints
-- Clone all the evidence bindings in
@@ -252,19 +268,13 @@ emitWanted origin pty
; emitSimple $ mkNonCanonical ev
; return $ ctEvTerm ev }
-emitDerivedEqs :: CtOrigin -> [(TcType,TcType)] -> TcM ()
--- Emit some new derived nominal equalities
-emitDerivedEqs origin pairs
+emitWantedEqs :: CtOrigin -> [(TcType,TcType)] -> TcM ()
+-- Emit some new wanted nominal equalities
+emitWantedEqs origin pairs
| null pairs
= return ()
| otherwise
- = do { loc <- getCtLocM origin Nothing
- ; emitSimples (listToBag (map (mk_one loc) pairs)) }
- where
- mk_one loc (ty1, ty2)
- = mkNonCanonical $
- CtDerived { ctev_pred = mkPrimEqPred ty1 ty2
- , ctev_loc = loc }
+ = mapM_ (uncurry (emitWantedEq origin TypeLevel Nominal)) pairs
-- | Emits a new equality constraint
emitWantedEq :: CtOrigin -> TypeOrKind -> Role -> TcType -> TcType -> TcM Coercion
@@ -272,8 +282,10 @@ emitWantedEq origin t_or_k role ty1 ty2
= do { hole <- newCoercionHole pty
; loc <- getCtLocM origin (Just t_or_k)
; emitSimple $ mkNonCanonical $
- CtWanted { ctev_pred = pty, ctev_dest = HoleDest hole
- , ctev_nosh = WDeriv, ctev_loc = loc }
+ CtWanted { ctev_pred = pty
+ , ctev_dest = HoleDest hole
+ , ctev_loc = loc
+ , ctev_rewriters = rewriterSetFromTypes [ty1, ty2] }
; return (HoleCo hole) }
where
pty = mkPrimEqPredRole role ty1 ty2
@@ -284,10 +296,10 @@ emitWantedEvVar :: CtOrigin -> TcPredType -> TcM EvVar
emitWantedEvVar origin ty
= do { new_cv <- newEvVar ty
; loc <- getCtLocM origin Nothing
- ; let ctev = CtWanted { ctev_dest = EvVarDest new_cv
- , ctev_pred = ty
- , ctev_nosh = WDeriv
- , ctev_loc = loc }
+ ; let ctev = CtWanted { ctev_dest = EvVarDest new_cv
+ , ctev_pred = ty
+ , ctev_loc = loc
+ , ctev_rewriters = emptyRewriterSet }
; emitSimple $ mkNonCanonical ctev
; return new_cv }
@@ -302,7 +314,7 @@ emitNewExprHole occ ty
; ref <- newTcRef (pprPanic "unfilled unbound-variable evidence" (ppr u))
; let her = HER ref ty u
- ; loc <- getCtLocM (ExprHoleOrigin occ) (Just TypeLevel)
+ ; loc <- getCtLocM (ExprHoleOrigin (Just occ)) (Just TypeLevel)
; let hole = Hole { hole_sort = ExprHole her
, hole_occ = occ
@@ -353,7 +365,7 @@ newImplication
newCoercionHole :: TcPredType -> TcM CoercionHole
newCoercionHole pred_ty
= do { co_var <- newEvVar pred_ty
- ; traceTc "New coercion hole:" (ppr co_var)
+ ; traceTc "New coercion hole:" (ppr co_var <+> dcolon <+> ppr pred_ty)
; ref <- newMutVar Nothing
; return $ CoercionHole { ch_co_var = co_var, ch_ref = ref } }
@@ -411,6 +423,24 @@ checkCoercionHole cv co
| otherwise
= False
+-- | A coercion hole used to store evidence for `Concrete#` constraints.
+--
+-- See Note [The Concrete mechanism].
+type ConcreteHole = CoercionHole
+
+-- | Create a new (initially unfilled) coercion hole,
+-- to hold evidence for a @'Concrete#' (ty :: ki)@ constraint.
+newConcreteHole :: Kind -- ^ Kind of the thing we want to ensure is concrete (e.g. 'runtimeRepTy')
+ -> Type -- ^ Thing we want to ensure is concrete (e.g. some 'RuntimeRep')
+ -> TcM (ConcreteHole, TcType)
+ -- ^ where to put the evidence, and a metavariable to store
+ -- the concrete type
+newConcreteHole ki ty
+ = do { concrete_ty <- newFlexiTyVarTy ki
+ ; let co_ty = mkHeteroPrimEqPred ki ki ty concrete_ty
+ ; hole <- newCoercionHole co_ty
+ ; return (hole, concrete_ty) }
+
{- **********************************************************************
*
ExpType functions
@@ -2465,14 +2495,11 @@ zonkSkolemInfoAnon (InferSkol ntys) = do { ntys' <- mapM do_one ntys
zonkSkolemInfoAnon skol_info = return skol_info
{-
-%************************************************************************
-%* *
-\subsection{Zonking -- the main work-horses: zonkTcType, zonkTcTyVar}
+************************************************************************
* *
-* For internal use only! *
+ Zonking -- the main work-horses: zonkTcType, zonkTcTyVar
* *
************************************************************************
-
-}
-- For unbound, mutable tyvars, zonkType uses the function given to it
@@ -2620,13 +2647,21 @@ zonkTidyOrigin env (KindEqOrigin ty1 ty2 orig t_or_k)
; return (env3, KindEqOrigin ty1' ty2' orig' t_or_k) }
zonkTidyOrigin env (FunDepOrigin1 p1 o1 l1 p2 o2 l2)
= do { (env1, p1') <- zonkTidyTcType env p1
- ; (env2, p2') <- zonkTidyTcType env1 p2
- ; return (env2, FunDepOrigin1 p1' o1 l1 p2' o2 l2) }
+ ; (env2, o1') <- zonkTidyOrigin env1 o1
+ ; (env3, p2') <- zonkTidyTcType env2 p2
+ ; (env4, o2') <- zonkTidyOrigin env3 o2
+ ; return (env4, FunDepOrigin1 p1' o1' l1 p2' o2' l2) }
zonkTidyOrigin env (FunDepOrigin2 p1 o1 p2 l2)
= do { (env1, p1') <- zonkTidyTcType env p1
; (env2, p2') <- zonkTidyTcType env1 p2
; (env3, o1') <- zonkTidyOrigin env2 o1
; return (env3, FunDepOrigin2 p1' o1' p2' l2) }
+zonkTidyOrigin env (InjTFOrigin1 pred1 orig1 loc1 pred2 orig2 loc2)
+ = do { (env1, pred1') <- zonkTidyTcType env pred1
+ ; (env2, orig1') <- zonkTidyOrigin env1 orig1
+ ; (env3, pred2') <- zonkTidyTcType env2 pred2
+ ; (env4, orig2') <- zonkTidyOrigin env3 orig2
+ ; return (env4, InjTFOrigin1 pred1' orig1' loc1 pred2' orig2' loc2) }
zonkTidyOrigin env (CycleBreakerOrigin orig)
= do { (env1, orig') <- zonkTidyOrigin env orig
; return (env1, CycleBreakerOrigin orig') }
@@ -2636,6 +2671,10 @@ zonkTidyOrigin env (InstProvidedOrigin mod cls_inst)
zonkTidyOrigin env (FixedRuntimeRepOrigin ty frr_orig)
= do { (env1, ty') <- zonkTidyTcType env ty
; return (env1, FixedRuntimeRepOrigin ty' frr_orig)}
+zonkTidyOrigin env (WantedSuperclassOrigin pty orig)
+ = do { (env1, pty') <- zonkTidyTcType env pty
+ ; (env2, orig') <- zonkTidyOrigin env1 orig
+ ; return (env2, WantedSuperclassOrigin pty' orig') }
zonkTidyOrigin env orig = return (env, orig)
zonkTidyOrigins :: TidyEnv -> [CtOrigin] -> TcM (TidyEnv, [CtOrigin])
@@ -2644,13 +2683,14 @@ zonkTidyOrigins = mapAccumLM zonkTidyOrigin
----------------
tidyCt :: TidyEnv -> Ct -> Ct
-- Used only in error reporting
-tidyCt env ct
- = ct { cc_ev = tidy_ev (ctEvidence ct) }
- where
- tidy_ev :: CtEvidence -> CtEvidence
+tidyCt env ct = ct { cc_ev = tidyCtEvidence env (ctEvidence ct) }
+
+tidyCtEvidence :: TidyEnv -> CtEvidence -> CtEvidence
-- NB: we do not tidy the ctev_evar field because we don't
-- show it in error messages
- tidy_ev ctev = ctev { ctev_pred = tidyType env (ctev_pred ctev) }
+tidyCtEvidence env ctev = ctev { ctev_pred = tidyType env ty }
+ where
+ ty = ctev_pred ctev
tidyHole :: TidyEnv -> Hole -> Hole
tidyHole env h@(Hole { hole_ty = ty }) = h { hole_ty = tidyType env ty }
@@ -2728,3 +2768,49 @@ naughtyQuantification orig_ty tv escapees
]
; failWithTcM (env, msg) }
+
+{-
+************************************************************************
+* *
+ Checking for coercion holes
+* *
+************************************************************************
+-}
+
+-- | Check whether any coercion hole in a RewriterSet is still unsolved.
+-- Does this by recursively looking through filled coercion holes until
+-- one is found that is not yet filled in, at which point this aborts.
+anyUnfilledCoercionHoles :: RewriterSet -> TcM Bool
+anyUnfilledCoercionHoles (RewriterSet set)
+ = nonDetStrictFoldUniqSet go (return False) set
+ -- this does not introduce non-determinism, because the only
+ -- monadic action is to read, and the combining function is
+ -- commutative
+ where
+ go :: CoercionHole -> TcM Bool -> TcM Bool
+ go hole m_acc = m_acc <||> check_hole hole
+
+ check_hole :: CoercionHole -> TcM Bool
+ check_hole hole = do { m_co <- unpackCoercionHole_maybe hole
+ ; case m_co of
+ Nothing -> return True -- unfilled hole
+ Just co -> unUCHM (check_co co) }
+
+ check_ty :: Type -> UnfilledCoercionHoleMonoid
+ check_co :: Coercion -> UnfilledCoercionHoleMonoid
+ (check_ty, _, check_co, _) = foldTyCo folder ()
+
+ folder :: TyCoFolder () UnfilledCoercionHoleMonoid
+ folder = TyCoFolder { tcf_view = noView
+ , tcf_tyvar = \ _ tv -> check_ty (tyVarKind tv)
+ , tcf_covar = \ _ cv -> check_ty (varType cv)
+ , tcf_hole = \ _ -> UCHM . check_hole
+ , tcf_tycobinder = \ _ _ _ -> () }
+
+newtype UnfilledCoercionHoleMonoid = UCHM { unUCHM :: TcM Bool }
+
+instance Semigroup UnfilledCoercionHoleMonoid where
+ UCHM l <> UCHM r = UCHM (l <||> r)
+
+instance Monoid UnfilledCoercionHoleMonoid where
+ mempty = UCHM (return False)