summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Eisenberg <rae@richarde.dev>2021-11-22 17:34:32 -0500
committerSimon Peyton Jones <simon.peytonjones@gmail.com>2023-01-11 08:30:42 +0000
commitaed1974e92366ab8e117734f308505684f70cddf (patch)
treebbfe7fdd00f1e0ef8dacdcf8d070a07efa38561b
parent083f701553852c4460159cd6deb2515d3373714d (diff)
downloadhaskell-wip/T20666.tar.gz
Refactor the treatment of loopy superclass dictswip/T20666
This patch completely re-engineers how we deal with loopy superclass dictionaries in instance declarations. It fixes #20666 and #19690 The highlights are * Recognise that the loopy-superclass business should use precisely the Paterson conditions. This is much much nicer. See Note [Recursive superclasses] in GHC.Tc.TyCl.Instance * With that in mind, define "Paterson-smaller" in Note [Paterson conditions] in GHC.Tc.Validity, and the new data type `PatersonSize` in GHC.Tc.Utils.TcType, along with functions to compute and compare PatsonSizes * Use the new PatersonSize stuff when solving superclass constraints See Note [Solving superclass constraints] in GHC.Tc.TyCl.Instance * In GHC.Tc.Solver.Monad.lookupInInerts, add a missing call to prohibitedSuperClassSolve. This was the original cause of #20666. * Treat (TypeError "stuff") as having PatersonSize zero. See Note [Paterson size for type family applications] in GHC.Tc.Utils.TcType. * Treat the head of a Wanted quantified constraint in the same way as the superclass of an instance decl; this is what fixes #19690. See GHC.Tc.Solver.Canonical Note [Solving a Wanted forall-constraint] (Thanks to Matthew Craven for this insight.) This entailed refactoring the GivenSc constructor of CtOrigin a bit, to say whether it comes from an instance decl or quantified constraint. * Some refactoring way in which redundant constraints are reported; we don't want to complain about the extra, apparently-redundant constraints that we must add to an instance decl because of the loopy-superclass thing. I moved some work from GHC.Tc.Errors to GHC.Tc.Solver. * Add a new section to the user manual to describe the loopy superclass issue and what rules it follows.
-rw-r--r--compiler/GHC/Core/InstEnv.hs4
-rw-r--r--compiler/GHC/Core/TyCo/FVs.hs7
-rw-r--r--compiler/GHC/Tc/Deriv.hs2
-rw-r--r--compiler/GHC/Tc/Deriv/Infer.hs57
-rw-r--r--compiler/GHC/Tc/Errors.hs31
-rw-r--r--compiler/GHC/Tc/Errors/Ppr.hs25
-rw-r--r--compiler/GHC/Tc/Gen/HsType.hs4
-rw-r--r--compiler/GHC/Tc/Solver.hs80
-rw-r--r--compiler/GHC/Tc/Solver/Canonical.hs114
-rw-r--r--compiler/GHC/Tc/Solver/InertSet.hs17
-rw-r--r--compiler/GHC/Tc/Solver/Interact.hs71
-rw-r--r--compiler/GHC/Tc/Solver/Monad.hs18
-rw-r--r--compiler/GHC/Tc/TyCl/Instance.hs204
-rw-r--r--compiler/GHC/Tc/Types/Constraint.hs5
-rw-r--r--compiler/GHC/Tc/Types/Origin.hs127
-rw-r--r--compiler/GHC/Tc/Utils/Backpack.hs31
-rw-r--r--compiler/GHC/Tc/Utils/Instantiate.hs26
-rw-r--r--compiler/GHC/Tc/Utils/TcMType.hs4
-rw-r--r--compiler/GHC/Tc/Utils/TcType.hs359
-rw-r--r--compiler/GHC/Tc/Utils/Unify.hs8
-rw-r--r--compiler/GHC/Tc/Validity.hs485
-rw-r--r--docs/users_guide/exts/instances.rst104
-rw-r--r--testsuite/tests/deriving/should_compile/T14339.hs14
-rw-r--r--testsuite/tests/deriving/should_fail/T21302.hs6
-rw-r--r--testsuite/tests/deriving/should_fail/T8165_fail2.stderr4
-rw-r--r--testsuite/tests/impredicative/T17332.stderr4
-rw-r--r--testsuite/tests/indexed-types/should_fail/NotRelaxedExamples.stderr11
-rw-r--r--testsuite/tests/indexed-types/should_fail/T10817.stderr4
-rw-r--r--testsuite/tests/indexed-types/should_fail/T13271.stderr7
-rw-r--r--testsuite/tests/indexed-types/should_fail/T15172.stderr2
-rw-r--r--testsuite/tests/indexed-types/should_fail/TyFamUndec.stderr11
-rw-r--r--testsuite/tests/quantified-constraints/T19690.hs15
-rw-r--r--testsuite/tests/quantified-constraints/T19690.stderr16
-rw-r--r--testsuite/tests/quantified-constraints/T19921.stderr5
-rw-r--r--testsuite/tests/quantified-constraints/T21006.stderr1
-rw-r--r--testsuite/tests/quantified-constraints/all.T1
-rw-r--r--testsuite/tests/typecheck/should_compile/T15473.stderr5
-rw-r--r--testsuite/tests/typecheck/should_compile/abstract_refinement_hole_fits.stderr56
-rw-r--r--testsuite/tests/typecheck/should_compile/constraint_hole_fits.stderr4
-rw-r--r--testsuite/tests/typecheck/should_compile/refinement_hole_fits.stderr20
-rw-r--r--testsuite/tests/typecheck/should_fail/T14884.stderr10
-rw-r--r--testsuite/tests/typecheck/should_fail/T15552a.stderr15
-rw-r--r--testsuite/tests/typecheck/should_fail/T15801.stderr1
-rw-r--r--testsuite/tests/typecheck/should_fail/T20666.hs19
-rw-r--r--testsuite/tests/typecheck/should_fail/T20666.stderr20
-rw-r--r--testsuite/tests/typecheck/should_fail/T20666a.hs12
-rw-r--r--testsuite/tests/typecheck/should_fail/T20666a.stderr10
-rw-r--r--testsuite/tests/typecheck/should_fail/all.T2
-rw-r--r--testsuite/tests/typecheck/should_fail/fd-loop.stderr4
-rw-r--r--testsuite/tests/typecheck/should_fail/tcfail108.stderr5
-rw-r--r--testsuite/tests/typecheck/should_fail/tcfail133.hs8
-rw-r--r--testsuite/tests/typecheck/should_fail/tcfail133.stderr6
-rw-r--r--testsuite/tests/typecheck/should_fail/tcfail154.stderr4
-rw-r--r--testsuite/tests/typecheck/should_fail/tcfail214.stderr2
54 files changed, 1293 insertions, 794 deletions
diff --git a/compiler/GHC/Core/InstEnv.hs b/compiler/GHC/Core/InstEnv.hs
index bb7315074f..f06f12e89a 100644
--- a/compiler/GHC/Core/InstEnv.hs
+++ b/compiler/GHC/Core/InstEnv.hs
@@ -232,10 +232,8 @@ pprInstances ispecs = vcat (map pprInstance ispecs)
instanceHead :: ClsInst -> ([TyVar], Class, [Type])
-- Returns the head, using the fresh tyvars from the ClsInst
-instanceHead (ClsInst { is_tvs = tvs, is_tys = tys, is_dfun = dfun })
+instanceHead (ClsInst { is_tvs = tvs, is_cls = cls, is_tys = tys })
= (tvs, cls, tys)
- where
- (_, _, cls, _) = tcSplitDFunTy (idType dfun)
-- | Collects the names of concrete types and type constructors that make
-- up the head of a class instance. For instance, given `class Foo a b`:
diff --git a/compiler/GHC/Core/TyCo/FVs.hs b/compiler/GHC/Core/TyCo/FVs.hs
index 3685876fa4..689503ef89 100644
--- a/compiler/GHC/Core/TyCo/FVs.hs
+++ b/compiler/GHC/Core/TyCo/FVs.hs
@@ -31,7 +31,7 @@ module GHC.Core.TyCo.FVs
noFreeVarsOfType, noFreeVarsOfTypes, noFreeVarsOfCo,
-- * Free type constructors
- tyConsOfType,
+ tyConsOfType, tyConsOfTypes,
-- * Free vars with visible/invisible separate
visVarsOfTypes, visVarsOfType,
@@ -1069,7 +1069,7 @@ tyConsOfType ty
go ty | Just ty' <- coreView ty = go ty'
go (TyVarTy {}) = emptyUniqSet
go (LitTy {}) = emptyUniqSet
- go (TyConApp tc tys) = go_tc tc `unionUniqSets` go_s tys
+ go (TyConApp tc tys) = go_tc tc `unionUniqSets` tyConsOfTypes tys
go (AppTy a b) = go a `unionUniqSets` go b
go (FunTy af w a b) = go w `unionUniqSets`
go a `unionUniqSets` go b
@@ -1108,12 +1108,13 @@ tyConsOfType ty
-- this last case can happen from the tyConsOfType used from
-- checkTauTvUpdate
- go_s tys = foldr (unionUniqSets . go) emptyUniqSet tys
go_cos cos = foldr (unionUniqSets . go_co) emptyUniqSet cos
go_tc tc = unitUniqSet tc
go_ax ax = go_tc $ coAxiomTyCon ax
+tyConsOfTypes :: [Type] -> UniqSet TyCon
+tyConsOfTypes tys = foldr (unionUniqSets . tyConsOfType) emptyUniqSet tys
{- **********************************************************************
* *
diff --git a/compiler/GHC/Tc/Deriv.hs b/compiler/GHC/Tc/Deriv.hs
index 4917b21a77..4d7bf81f6c 100644
--- a/compiler/GHC/Tc/Deriv.hs
+++ b/compiler/GHC/Tc/Deriv.hs
@@ -28,7 +28,7 @@ import GHC.Tc.Deriv.Utils
import GHC.Tc.TyCl.Class( instDeclCtxt3, tcATDefault )
import GHC.Tc.Utils.Env
import GHC.Tc.Deriv.Generate
-import GHC.Tc.Validity( allDistinctTyVars, checkValidInstHead )
+import GHC.Tc.Validity( checkValidInstHead )
import GHC.Core.InstEnv
import GHC.Tc.Utils.Instantiate
import GHC.Core.FamInstEnv
diff --git a/compiler/GHC/Tc/Deriv/Infer.hs b/compiler/GHC/Tc/Deriv/Infer.hs
index feba275d75..e90811979f 100644
--- a/compiler/GHC/Tc/Deriv/Infer.hs
+++ b/compiler/GHC/Tc/Deriv/Infer.hs
@@ -51,7 +51,6 @@ import GHC.Utils.Misc
import GHC.Types.Basic
import GHC.Types.Var
-import GHC.Types.Var.Set
import GHC.Data.Bag
@@ -701,7 +700,7 @@ simplifyInstanceContexts infer_specs
current_solns infer_specs
; new_solns <- checkNoErrs $
extendLocalInstEnv inst_specs $
- mapM gen_soln infer_specs
+ mapM simplifyDeriv infer_specs
; if (current_solns `eqSolution` new_solns) then
return [ setDerivSpecTheta soln spec
@@ -713,24 +712,6 @@ simplifyInstanceContexts infer_specs
-- Canonicalise for comparison
-- See Note [Deterministic simplifyInstanceContexts]
canSolution = map (sortBy nonDetCmpType)
- ------------------------------------------------------------------
- gen_soln :: DerivSpec ThetaSpec -> TcM ThetaType
- gen_soln (DS { ds_loc = loc, ds_tvs = tyvars
- , ds_cls = clas, ds_tys = inst_tys, ds_theta = deriv_rhs
- , ds_skol_info = skol_info, ds_user_ctxt = user_ctxt })
- = setSrcSpan loc $
- addErrCtxt (derivInstCtxt the_pred) $
- do { theta <- simplifyDeriv skol_info user_ctxt tyvars deriv_rhs
- -- checkValidInstance tyvars theta clas inst_tys
- -- Not necessary; see Note [Exotic derived instance contexts]
-
- ; traceTc "GHC.Tc.Deriv" (ppr deriv_rhs $$ ppr theta)
- -- Claim: the result instance declaration is guaranteed valid
- -- Hence no need to call:
- -- checkValidInstance tyvars theta clas inst_tys
- ; return theta }
- where
- the_pred = mkClassPred clas inst_tys
derivInstCtxt :: PredType -> SDoc
derivInstCtxt pred
@@ -744,29 +725,27 @@ derivInstCtxt pred
***********************************************************************************
-}
+
-- | Given @instance (wanted) => C inst_ty@, simplify 'wanted' as much
-- as possible. Fail if not possible.
-simplifyDeriv :: SkolemInfo -- ^ The 'SkolemInfo' used to skolemise the
- -- 'TcTyVar' arguments
- -> UserTypeCtxt -- ^ Used to inform error messages as to whether
- -- we are in a @deriving@ clause or a standalone
- -- @deriving@ declaration
- -> [TcTyVar] -- ^ The tyvars bound by @inst_ty@.
- -> ThetaSpec -- ^ The constraints to solve and simplify
+simplifyDeriv :: DerivSpec ThetaSpec
-> TcM ThetaType -- ^ Needed constraints (after simplification),
-- i.e. @['PredType']@.
-simplifyDeriv skol_info user_ctxt tvs theta
- = do { let skol_set = mkVarSet tvs
-
+simplifyDeriv (DS { ds_loc = loc, ds_tvs = tvs
+ , ds_cls = clas, ds_tys = inst_tys, ds_theta = deriv_rhs
+ , ds_skol_info = skol_info, ds_user_ctxt = user_ctxt })
+ = setSrcSpan loc $
+ addErrCtxt (derivInstCtxt (mkClassPred clas inst_tys)) $
+ do {
-- See [STEP DAC BUILD]
-- Generate the implication constraints, one for each method, to solve
-- with the skolemized variables. Start "one level down" because
-- we are going to wrap the result in an implication with tvs,
-- in step [DAC RESIDUAL]
- ; (tc_lvl, wanteds) <- captureThetaSpecConstraints user_ctxt theta
+ ; (tc_lvl, wanteds) <- captureThetaSpecConstraints user_ctxt deriv_rhs
; traceTc "simplifyDeriv inputs" $
- vcat [ pprTyVars tvs $$ ppr theta $$ ppr wanteds, ppr skol_info ]
+ vcat [ pprTyVars tvs $$ ppr deriv_rhs $$ ppr wanteds, ppr skol_info ]
-- See [STEP DAC SOLVE]
-- Simplify the constraints, starting at the same level at which
@@ -783,6 +762,7 @@ simplifyDeriv skol_info user_ctxt tvs theta
-- From the simplified constraints extract a subset 'good' that will
-- become the context 'min_theta' for the derived instance.
; let residual_simple = approximateWC True solved_wanteds
+ head_size = pSizeClassPred clas inst_tys
good = mapMaybeBag get_good residual_simple
-- Returns @Just p@ (where @p@ is the type of the Ct) if a Ct is
@@ -791,10 +771,8 @@ simplifyDeriv skol_info user_ctxt tvs theta
-- See Note [Exotic derived instance contexts] for what
-- constitutes an exotic constraint.
get_good :: Ct -> Maybe PredType
- get_good ct | validDerivPred skol_set p
- = Just p
- | otherwise
- = Nothing
+ get_good ct | validDerivPred head_size p = Just p
+ | otherwise = Nothing
where p = ctPred ct
; traceTc "simplifyDeriv outputs" $
@@ -824,6 +802,13 @@ simplifyDeriv skol_info user_ctxt tvs theta
-- in this line of code.
; simplifyTopImplic leftover_implic
+ ; traceTc "GHC.Tc.Deriv" (ppr deriv_rhs $$ ppr min_theta)
+
+ -- Claim: the result instance declaration is guaranteed valid
+ -- Hence no need to call:
+ -- checkValidInstance tyvars theta clas inst_tys
+ -- See Note [Exotic derived instance contexts]
+
; return min_theta }
{-
diff --git a/compiler/GHC/Tc/Errors.hs b/compiler/GHC/Tc/Errors.hs
index 61caa2e456..c22ab6a2e5 100644
--- a/compiler/GHC/Tc/Errors.hs
+++ b/compiler/GHC/Tc/Errors.hs
@@ -391,7 +391,7 @@ reportImplic ctxt implic@(Implic { ic_skols = tvs
warnRedundantConstraints :: SolverReportErrCtxt -> TcLclEnv -> SkolemInfoAnon -> [EvVar] -> TcM ()
-- See Note [Tracking redundant constraints] in GHC.Tc.Solver
-warnRedundantConstraints ctxt env info ev_vars
+warnRedundantConstraints ctxt env info redundant_evs
| null redundant_evs
= return ()
@@ -423,18 +423,6 @@ warnRedundantConstraints ctxt env info ev_vars
[]
; reportDiagnostic msg }
- redundant_evs =
- filterOut is_type_error $
- case info of -- See Note [Redundant constraints in instance decls]
- InstSkol -> filterOut (improving . idType) ev_vars
- _ -> ev_vars
-
- -- See #15232
- is_type_error = isJust . userTypeError_maybe . idType
-
- improving pred -- (transSuperClasses p) does not include p
- = any isImprovementPred (pred : transSuperClasses pred)
-
reportBadTelescope :: SolverReportErrCtxt -> TcLclEnv -> SkolemInfoAnon -> [TcTyVar] -> TcM ()
reportBadTelescope ctxt env (ForAllSkol telescope) skols
= do { msg <- mkErrorReport
@@ -449,23 +437,6 @@ reportBadTelescope ctxt env (ForAllSkol telescope) skols
reportBadTelescope _ _ skol_info skols
= pprPanic "reportBadTelescope" (ppr skol_info $$ ppr skols)
-{- Note [Redundant constraints in instance decls]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-For instance declarations, we don't report unused givens if
-they can give rise to improvement. Example (#10100):
- class Add a b ab | a b -> ab, a ab -> b
- instance Add Zero b b
- instance Add a b ab => Add (Succ a) b (Succ ab)
-The context (Add a b ab) for the instance is clearly unused in terms
-of evidence, since the dictionary has no fields. But it is still
-needed! With the context, a wanted constraint
- Add (Succ Zero) beta (Succ Zero)
-we will reduce to (Add Zero beta Zero), and thence we get beta := Zero.
-But without the context we won't find beta := Zero.
-
-This only matters in instance declarations..
--}
-
-- | Should we completely ignore this constraint in error reporting?
-- It *must* be the case that any constraint for which this returns True
-- somehow causes an error to be reported elsewhere.
diff --git a/compiler/GHC/Tc/Errors/Ppr.hs b/compiler/GHC/Tc/Errors/Ppr.hs
index 8d18cad2a2..2e17295073 100644
--- a/compiler/GHC/Tc/Errors/Ppr.hs
+++ b/compiler/GHC/Tc/Errors/Ppr.hs
@@ -2618,7 +2618,7 @@ pprTcSolverReportMsg ctxt@(CEC {cec_encl = implics})
-- Don't suggest fixes for the provided context of a pattern
-- synonym; the right fix is to bind more in the pattern
show_fixes (ctxtFixes has_ambigs pred implics
- ++ drv_fixes)
+ ++ drv_fixes ++ naked_sc_fixes)
, ppWhen (not (null candidates))
(hang (text "There are instances for similar types:")
2 (vcat (map ppr candidates)))
@@ -2689,7 +2689,7 @@ pprTcSolverReportMsg ctxt@(CEC {cec_encl = implics})
StandAloneDerivOrigin -> [drv_fix True]
DerivOriginDC _ _ standalone -> [drv_fix standalone]
DerivOriginCoerce _ _ _ standalone -> [drv_fix standalone]
- _ -> []
+ _ -> []
drv_fix standalone_wildcard
| standalone_wildcard
@@ -2698,6 +2698,25 @@ pprTcSolverReportMsg ctxt@(CEC {cec_encl = implics})
= hang (text "use a standalone 'deriving instance' declaration,")
2 (text "so you can specify the instance context yourself")
+ -- naked_sc_fix: try to produce a helpful error message for
+ -- superclass constraints caught by the subtleties described by
+ -- Note [Recursive superclasses] in GHC.TyCl.Instance
+ naked_sc_fixes
+ | ScOrigin _ NakedSc <- orig -- A superclass wanted with no instance decls used yet
+ , any non_tyvar_preds useful_givens -- Some non-tyvar givens
+ = [vcat [ text "If the constraint looks soluble from a superclass of the instance context,"
+ , text "read 'Undecidable instances and loopy superclasses' in the user manual" ]]
+ | otherwise = []
+
+ non_tyvar_preds :: UserGiven -> Bool
+ non_tyvar_preds = any non_tyvar_pred . ic_given
+
+ non_tyvar_pred :: EvVar -> Bool
+ -- Tells if the Given is of form (C ty1 .. tyn), where the tys are not all tyvars
+ non_tyvar_pred given = case getClassPredTys_maybe (idType given) of
+ Just (_, tys) -> not (all isTyVarTy tys)
+ Nothing -> False
+
pprTcSolverReportMsg (CEC {cec_encl = implics}) (OverlappingInstances item matches unifiers) =
vcat
[ addArising ct_loc $
@@ -3529,7 +3548,7 @@ show_fixes (f:fs) = sep [ text "Possible fix:"
ctxtFixes :: Bool -> PredType -> [Implication] -> [SDoc]
ctxtFixes has_ambig_tvs pred implics
| not has_ambig_tvs
- , isTyVarClassPred pred
+ , isTyVarClassPred pred -- Don't suggest adding (Eq T) to the context, say
, (skol:skols) <- usefulContext implics pred
, let what | null skols
, SigSkol (PatSynCtxt {}) _ _ <- skol
diff --git a/compiler/GHC/Tc/Gen/HsType.hs b/compiler/GHC/Tc/Gen/HsType.hs
index 0ea0412339..bf15393048 100644
--- a/compiler/GHC/Tc/Gen/HsType.hs
+++ b/compiler/GHC/Tc/Gen/HsType.hs
@@ -664,7 +664,9 @@ tcDerivStrategy mb_lds
tc_deriv_strategy (NewtypeStrategy _) = boring_case (NewtypeStrategy noExtField)
tc_deriv_strategy (ViaStrategy hs_sig)
= do { ty <- tcTopLHsType DerivClauseCtxt hs_sig
- ; rec { (via_tvs, via_pred) <- tcSkolemiseInvisibleBndrs (DerivSkol via_pred) ty}
+ -- rec {..}: see Note [Keeping SkolemInfo inside a SkolemTv]
+ -- in GHC.Tc.Utils.TcType
+ ; rec { (via_tvs, via_pred) <- tcSkolemiseInvisibleBndrs (DerivSkol via_pred) ty }
; pure (ViaStrategy via_pred, via_tvs) }
boring_case :: ds -> TcM (ds, [a])
diff --git a/compiler/GHC/Tc/Solver.hs b/compiler/GHC/Tc/Solver.hs
index cdc15959f8..6fc5b28ab0 100644
--- a/compiler/GHC/Tc/Solver.hs
+++ b/compiler/GHC/Tc/Solver.hs
@@ -73,7 +73,7 @@ import Control.Monad
import Data.Foldable ( toList )
import Data.List ( partition )
import Data.List.NonEmpty ( NonEmpty(..) )
-import GHC.Data.Maybe ( mapMaybe )
+import GHC.Data.Maybe ( mapMaybe, isJust )
{-
*********************************************************************************
@@ -1199,10 +1199,12 @@ simplifyInfer rhs_tclvl infer_mode sigs name_taus wanteds
-- NB: bound_theta are constraints we want to quantify over,
-- including the psig_theta, which we always quantify over
-- NB: bound_theta are fully zonked
+ -- rec {..}: see Note [Keeping SkolemInfo inside a SkolemTv]
+ -- in GHC.Tc.Utils.TcType
; rec { (qtvs, bound_theta, co_vars) <- decideQuantification skol_info infer_mode rhs_tclvl
name_taus partial_sigs
quant_pred_candidates
- ; bound_theta_vars <- mapM TcM.newEvVar bound_theta
+ ; bound_theta_vars <- mapM TcM.newEvVar bound_theta
; let full_theta = map idType bound_theta_vars
; skol_info <- mkSkolemInfo (InferSkol [ (name, mkSigmaTy [] full_theta ty)
@@ -2490,18 +2492,7 @@ setImplicationStatus implic@(Implic { ic_status = status
; bad_telescope <- checkBadTelescope implic
- ; let (used_givens, unused_givens)
- | warnRedundantGivens info
- = partition (`elemVarSet` need_inner) givens
- | otherwise = (givens, []) -- None to report
-
- minimal_used_givens = mkMinimalBySCs evVarPred used_givens
- is_minimal = (`elemVarSet` mkVarSet minimal_used_givens)
-
- warn_givens
- | not (null unused_givens) = unused_givens
- | warnRedundantGivens info = filterOut is_minimal used_givens
- | otherwise = []
+ ; let warn_givens = findUnnecessaryGivens info need_inner givens
discard_entire_implication -- Can we discard the entire implication?
= null warn_givens -- No warning from this implication
@@ -2541,6 +2532,67 @@ setImplicationStatus implic@(Implic { ic_status = status
| otherwise
= True -- Otherwise, keep it
+findUnnecessaryGivens :: SkolemInfoAnon -> VarSet -> [EvVar] -> [EvVar]
+findUnnecessaryGivens info need_inner givens
+ | not (warnRedundantGivens info) -- Don't report redundant constraints at all
+ = []
+
+ | not (null unused_givens) -- Some givens are literally unused
+ = unused_givens
+
+ | otherwise -- All givens are used, but some might
+ = redundant_givens -- still be redundant e.g. (Eq a, Ord a)
+
+ where
+ in_instance_decl = case info of { InstSkol {} -> True; _ -> False }
+ -- See Note [Redundant constraints in instance decls]
+
+ unused_givens = filterOut is_used givens
+
+ is_used given = is_type_error given
+ || (given `elemVarSet` need_inner)
+ || (in_instance_decl && is_improving (idType given))
+
+ minimal_givens = mkMinimalBySCs evVarPred givens
+ is_minimal = (`elemVarSet` mkVarSet minimal_givens)
+ redundant_givens
+ | in_instance_decl = []
+ | otherwise = filterOut is_minimal givens
+
+ -- See #15232
+ is_type_error = isJust . userTypeError_maybe . idType
+
+ is_improving pred -- (transSuperClasses p) does not include p
+ = any isImprovementPred (pred : transSuperClasses pred)
+
+{- Note [Redundant constraints in instance decls]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Instance declarations are special in two ways:
+
+* We don't report unused givens if they can give rise to improvement.
+ Example (#10100):
+ class Add a b ab | a b -> ab, a ab -> b
+ instance Add Zero b b
+ instance Add a b ab => Add (Succ a) b (Succ ab)
+ The context (Add a b ab) for the instance is clearly unused in terms
+ of evidence, since the dictionary has no fields. But it is still
+ needed! With the context, a wanted constraint
+ Add (Succ Zero) beta (Succ Zero)
+ we will reduce to (Add Zero beta Zero), and thence we get beta := Zero.
+ But without the context we won't find beta := Zero.
+
+ This only matters in instance declarations.
+
+* We don't report givens that are a superclass of another given. E.g.
+ class Ord r => UserOfRegs r a where ...
+ instance (Ord r, UserOfRegs r CmmReg) => UserOfRegs r CmmExpr where
+ The (Ord r) is not redundant, even though it is a superclass of
+ (UserOfRegs r CmmReg). See Note [Recursive superclasses] in GHC.Tc.TyCl.Instance.
+
+ Again this is specific to instance declarations.
+-}
+
+
checkBadTelescope :: Implication -> TcS Bool
-- True <=> the skolems form a bad telescope
-- See Note [Checking telescopes] in GHC.Tc.Types.Constraint
diff --git a/compiler/GHC/Tc/Solver/Canonical.hs b/compiler/GHC/Tc/Solver/Canonical.hs
index 33ee8e854c..02ce8115ad 100644
--- a/compiler/GHC/Tc/Solver/Canonical.hs
+++ b/compiler/GHC/Tc/Solver/Canonical.hs
@@ -1,6 +1,7 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE MultiWayIf #-}
+{-# LANGUAGE RecursiveDo #-}
module GHC.Tc.Solver.Canonical(
canonicalize,
@@ -530,7 +531,7 @@ mk_strict_superclasses rec_clss (CtGiven { ctev_evar = evar, ctev_loc = loc })
classSCSelIds cls
where
dict_ids = mkTemplateLocals theta
- size = sizeTypes tys
+ this_size = pSizeClassPred cls tys
do_one_given sel_id
| isUnliftedType sc_pred
@@ -570,37 +571,38 @@ mk_strict_superclasses rec_clss (CtGiven { ctev_evar = evar, ctev_loc = loc })
`App` (evId evar `mkVarApps` (tvs ++ dict_ids))
`mkVarApps` sc_tvs
- sc_loc
- | isCTupleClass cls
- = loc -- For tuple predicates, just take them apart, without
- -- adding their (large) size into the chain. When we
- -- get down to a base predicate, we'll include its size.
- -- #10335
-
- | isEqPredClass cls
- || cls `hasKey` coercibleTyConKey
- = loc -- The only superclasses of ~, ~~, and Coercible are primitive
- -- equalities, and they don't use the InstSCOrigin mechanism
- -- detailed in Note [Solving superclass constraints] in
- -- GHC.Tc.TyCl.Instance. Skip for a tiny performance win.
-
- -- See Note [Solving superclass constraints] in GHC.Tc.TyCl.Instance
- -- for explanation of InstSCOrigin and Note [Replacement vs keeping] in
- -- GHC.Tc.Solver.Interact for why we need OtherSCOrigin and depths
- | otherwise
- = loc { ctl_origin = new_orig }
- where
- new_orig = case ctLocOrigin loc of
- -- these cases are when we have something that's already a superclass constraint
- InstSCOrigin sc_depth n -> InstSCOrigin (sc_depth + 1) (n `max` size)
- OtherSCOrigin sc_depth si -> OtherSCOrigin (sc_depth + 1) si
-
- -- these cases do not already have a superclass constraint: depth starts at 1
- GivenOrigin InstSkol -> InstSCOrigin 1 size
- GivenOrigin other_skol -> OtherSCOrigin 1 other_skol
-
- other_orig -> pprPanic "Given constraint without given origin" $
- ppr evar $$ ppr other_orig
+ sc_loc | isCTupleClass cls
+ = loc -- For tuple predicates, just take them apart, without
+ -- adding their (large) size into the chain. When we
+ -- get down to a base predicate, we'll include its size.
+ -- #10335
+
+ | isEqPredClass cls || cls `hasKey` coercibleTyConKey
+ = loc -- The only superclasses of ~, ~~, and Coercible are primitive
+ -- equalities, and they don't use the GivenSCOrigin mechanism
+ -- detailed in Note [Solving superclass constraints] in
+ -- GHC.Tc.TyCl.Instance. Skip for a tiny performance win.
+
+ | otherwise
+ = loc { ctl_origin = mk_sc_origin (ctLocOrigin loc) }
+
+ -- See Note [Solving superclass constraints] in GHC.Tc.TyCl.Instance
+ -- for explanation of GivenSCOrigin and Note [Replacement vs keeping] in
+ -- GHC.Tc.Solver.Interact for why we need depths
+ mk_sc_origin :: CtOrigin -> CtOrigin
+ mk_sc_origin (GivenSCOrigin skol_info sc_depth already_blocked)
+ = GivenSCOrigin skol_info (sc_depth + 1)
+ (already_blocked || newly_blocked skol_info)
+
+ mk_sc_origin (GivenOrigin skol_info)
+ = -- These cases do not already have a superclass constraint: depth starts at 1
+ GivenSCOrigin skol_info 1 (newly_blocked skol_info)
+
+ mk_sc_origin other_orig = pprPanic "Given constraint without given origin" $
+ ppr evar $$ ppr other_orig
+
+ newly_blocked (InstSkol _ head_size) = isJust (this_size `ltPatersonSize` head_size)
+ newly_blocked _ = False
mk_strict_superclasses rec_clss ev tvs theta cls tys
| all noFreeVarsOfType tys
@@ -861,16 +863,27 @@ solveForAll ev@(CtWanted { ctev_dest = dest, ctev_rewriters = rewriters, ctev_lo
-- This setLclEnv is important: the emitImplicationTcS uses that
-- TcLclEnv for the implication, and that in turn sets the location
-- for the Givens when solving the constraint (#21006)
- do { skol_info <- mkSkolemInfo QuantCtxtSkol
- ; let empty_subst = mkEmptySubst $ mkInScopeSet $
+ do { let empty_subst = mkEmptySubst $ mkInScopeSet $
tyCoVarsOfTypes (pred:theta) `delVarSetList` tvs
- ; (subst, skol_tvs) <- tcInstSkolTyVarsX skol_info empty_subst tvs
- ; given_ev_vars <- mapM newEvVar (substTheta subst theta)
-
+ is_qc = IsQC (ctLocOrigin loc)
+
+ -- rec {..}: see Note [Keeping SkolemInfo inside a SkolemTv]
+ -- in GHC.Tc.Utils.TcType
+ -- Very like the code in tcSkolDFunType
+ ; rec { skol_info <- mkSkolemInfo skol_info_anon
+ ; (subst, skol_tvs) <- tcInstSkolTyVarsX skol_info empty_subst tvs
+ ; let inst_pred = substTy subst pred
+ inst_theta = substTheta subst theta
+ skol_info_anon = InstSkol is_qc (get_size inst_pred) }
+
+ ; given_ev_vars <- mapM newEvVar inst_theta
; (lvl, (w_id, wanteds))
<- pushLevelNoWorkList (ppr skol_info) $
- do { wanted_ev <- newWantedEvVarNC loc rewriters $
- substTy subst pred
+ do { let loc' = setCtLocOrigin loc (ScOrigin is_qc NakedSc)
+ -- Set the thing to prove to have a ScOrigin, so we are
+ -- careful about its termination checks.
+ -- See (QC-INV) in Note [Solving a Wanted forall-constraint]
+ ; wanted_ev <- newWantedEvVarNC loc' rewriters inst_pred
; return ( ctEvEvId wanted_ev
, unitBag (mkNonCanonical wanted_ev)) }
@@ -882,6 +895,12 @@ solveForAll ev@(CtWanted { ctev_dest = dest, ctev_rewriters = rewriters, ctev_lo
, et_binds = ev_binds, et_body = w_id }
; stopWith ev "Wanted forall-constraint" }
+ where
+ -- Getting the size of the head is a bit horrible
+ -- because of the special treament for class predicates
+ get_size pred = case classifyPredType pred of
+ ClassPred cls tys -> pSizeClassPred cls tys
+ _ -> pSizeType pred
-- See Note [Solving a Given forall-constraint]
solveForAll ev@(CtGiven {}) tvs _theta pred pend_sc
@@ -902,6 +921,23 @@ and discharge df thus:
where <binds> is filled in by solving the implication constraint.
All the machinery is to hand; there is little to do.
+The tricky point is about termination: see #19690. We want to maintain
+the invariant (QC-INV):
+
+ (QC-INV) Every quantified constraint returns a non-bottom dictionary
+
+just as every top-level instance declaration guarantees to return a non-bottom
+dictionary. But as #19690 shows, it is possible to get a bottom dicionary
+by superclass selection if we aren't careful. The situation is very similar
+to that described in Note [Recursive superclasses] in GHC.Tc.TyCl.Instance;
+and we use the same solution:
+
+* Give the Givens a CtOrigin of (GivenOrigin (InstSkol IsQC head_size))
+* Give the Wanted a CtOrigin of (ScOrigin IsQC NakedSc)
+
+Both of these things are done in solveForAll. Now the mechanism described
+in Note [Solving superclass constraints] in GHC.Tc.TyCl.Instance takes over.
+
Note [Solving a Given forall-constraint]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For a Given constraint
diff --git a/compiler/GHC/Tc/Solver/InertSet.hs b/compiler/GHC/Tc/Solver/InertSet.hs
index b3dcb3f5b1..5dc3431b9a 100644
--- a/compiler/GHC/Tc/Solver/InertSet.hs
+++ b/compiler/GHC/Tc/Solver/InertSet.hs
@@ -1633,12 +1633,17 @@ mightEqualLater inert_set given_pred given_loc wanted_pred wanted_loc
= False
can_unify lhs_tv _other _rhs_ty = mentions_meta_ty_var lhs_tv
-prohibitedSuperClassSolve :: CtLoc -> CtLoc -> Bool
--- See Note [Solving superclass constraints] in GHC.Tc.TyCl.Instance
-prohibitedSuperClassSolve from_loc solve_loc
- | InstSCOrigin _ given_size <- ctLocOrigin from_loc
- , ScOrigin wanted_size <- ctLocOrigin solve_loc
- = given_size >= wanted_size
+prohibitedSuperClassSolve :: CtLoc -- ^ is it loopy to use this one ...
+ -> CtLoc -- ^ ... to solve this one?
+ -> Bool -- ^ True ==> don't solve it
+-- See Note [Solving superclass constraints] in GHC.Tc.TyCl.Instance, (sc2)
+prohibitedSuperClassSolve given_loc wanted_loc
+ | GivenSCOrigin _ _ blocked <- ctLocOrigin given_loc
+ , blocked
+ , ScOrigin _ NakedSc <- ctLocOrigin wanted_loc
+ = True -- Prohibited if the Wanted is a superclass
+ -- and the Given has come via a superclass selection from
+ -- a predicate bigger than the head
| otherwise
= False
diff --git a/compiler/GHC/Tc/Solver/Interact.hs b/compiler/GHC/Tc/Solver/Interact.hs
index c3aa2d2695..e69e7ae0fe 100644
--- a/compiler/GHC/Tc/Solver/Interact.hs
+++ b/compiler/GHC/Tc/Solver/Interact.hs
@@ -6,8 +6,7 @@ module GHC.Tc.Solver.Interact (
) where
import GHC.Prelude
-import GHC.Types.Basic ( SwapFlag(..),
- infinity, IntWithInf, intGtLimit )
+import GHC.Types.Basic ( SwapFlag(..), IntWithInf, intGtLimit )
import GHC.Tc.Solver.Canonical
import GHC.Types.Var.Set
@@ -520,17 +519,18 @@ solveOneFromTheOther ct_i ct_w
pred = ctEvPred ev_i
- loc_i = ctEvLoc ev_i
- loc_w = ctEvLoc ev_w
- lvl_i = ctLocLevel loc_i
- lvl_w = ctLocLevel loc_w
+ loc_i = ctEvLoc ev_i
+ loc_w = ctEvLoc ev_w
+ orig_i = ctLocOrigin loc_i
+ orig_w = ctLocOrigin loc_w
+ lvl_i = ctLocLevel loc_i
+ lvl_w = ctLocLevel loc_w
is_psc_w = isPendingScDict ct_w
is_psc_i = isPendingScDict ct_i
- is_wsc_orig_i = is_wanted_superclass_loc loc_i
- is_wsc_orig_w = is_wanted_superclass_loc loc_w
- is_wanted_superclass_loc = isWantedSuperclassOrigin . ctLocOrigin
+ is_wsc_orig_i = isWantedSuperclassOrigin orig_i
+ is_wsc_orig_w = isWantedSuperclassOrigin orig_w
different_level_strategy -- Both Given
| isIPLikePred pred = if lvl_w > lvl_i then KeepWork else KeepInert
@@ -539,27 +539,20 @@ solveOneFromTheOther ct_i ct_w
-- For the isIPLikePred case see Note [Shadowing of Implicit Parameters]
same_level_strategy -- Both Given
- = case (ctLocOrigin loc_i, ctLocOrigin loc_w) of
- -- case 2(a) from Note [Replacement vs keeping]
- (InstSCOrigin _depth_i size_i, InstSCOrigin _depth_w size_w)
- | size_w < size_i -> KeepWork
- | otherwise -> KeepInert
+ = case (orig_i, orig_w) of
- -- case 2(c) from Note [Replacement vs keeping]
- (InstSCOrigin depth_i _, OtherSCOrigin depth_w _) -> choose_shallower depth_i depth_w
- (OtherSCOrigin depth_i _, InstSCOrigin depth_w _) -> choose_shallower depth_i depth_w
- (OtherSCOrigin depth_i _, OtherSCOrigin depth_w _) -> choose_shallower depth_i depth_w
+ (GivenSCOrigin _ depth_i blocked_i, GivenSCOrigin _ depth_w blocked_w)
+ | blocked_i, not blocked_w -> KeepWork -- Case 2(a) from
+ | not blocked_i, blocked_w -> KeepInert -- Note [Replacement vs keeping]
- -- case 2(b) from Note [Replacement vs keeping]
- (InstSCOrigin {}, _) -> KeepWork
- (OtherSCOrigin {}, _) -> KeepWork
+ -- Both blocked or both not blocked
- -- case 2(d) from Note [Replacement vs keeping]
- _ -> KeepInert
+ | depth_w < depth_i -> KeepWork -- Case 2(c) from
+ | otherwise -> KeepInert -- Note [Replacement vs keeping]
- choose_shallower depth_i depth_w | depth_w < depth_i = KeepWork
- | otherwise = KeepInert
- -- favor KeepInert in the equals case, according to 2(d) from the Note
+ (GivenSCOrigin {}, _) -> KeepWork -- Case 2(b) from Note [Replacement vs keeping]
+
+ _ -> KeepInert -- Case 2(d) from Note [Replacement vs keeping]
{-
Note [Replacement vs keeping]
@@ -585,7 +578,7 @@ solveOneFromTheOther.
2) Constraints coming from the same level (i.e. same implication)
- (a) If both are InstSCOrigin, choose the one with the smallest TypeSize,
+ (a) If both are GivenSCOrigin, choose the one that is unblocked if possible
according to Note [Solving superclass constraints] in GHC.Tc.TyCl.Instance.
(b) Prefer constraints that are not superclass selections. Example:
@@ -601,11 +594,12 @@ solveOneFromTheOther.
Getting this wrong was #20602. See also
Note [Tracking redundant constraints] in GHC.Tc.Solver.
- (c) If both are superclass selections (but not both InstSCOrigin), choose the one
- with the shallower superclass-selection depth, in the hope of identifying
- more correct redundant constraints. This is really a generalization of
- point (b), because the superclass depth of a non-superclass
- constraint is 0.
+ (c) If both are GivenSCOrigin, chooose the one with the shallower
+ superclass-selection depth, in the hope of identifying more correct
+ redundant constraints. This is really a generalization of point (b),
+ because the superclass depth of a non-superclass constraint is 0.
+
+ (If the levels differ, we definitely won't have both with GivenSCOrigin.)
(d) Finally, when there is still a choice, use KeepInert rather than
KeepWork, for two reasons:
@@ -669,7 +663,10 @@ interactIrred inerts ct_w@(CIrredCan { cc_ev = ev_w, cc_reason = reason })
-- See Note [Multiple matching irreds]
, let ev_i = ctEvidence ct_i
= do { what_next <- solveOneFromTheOther ct_i ct_w
- ; traceTcS "iteractIrred" (ppr ct_w $$ ppr what_next $$ ppr ct_i)
+ ; traceTcS "iteractIrred" $
+ vcat [ text "wanted:" <+> (ppr ct_w $$ ppr (ctOrigin ct_w))
+ , text "inert: " <+> (ppr ct_i $$ ppr (ctOrigin ct_i))
+ , ppr what_next ]
; case what_next of
KeepInert -> do { setEvBindIfWanted ev_w (swap_me swap ev_i)
; return (Stop ev_w (text "Irred equal" <+> parens (ppr what_next))) }
@@ -2326,9 +2323,11 @@ checkInstanceOK loc what pred
origin = ctLocOrigin loc
zap_origin loc -- After applying an instance we can set ScOrigin to
- -- infinity, so that prohibitedSuperClassSolve never fires
- | ScOrigin {} <- origin
- = setCtLocOrigin loc (ScOrigin infinity)
+ -- NotNakedSc, so that prohibitedSuperClassSolve never fires
+ -- See Note [Solving superclass constraints] in
+ -- GHC.Tc.TyCl.Instance, (sc1).
+ | ScOrigin what _ <- origin
+ = setCtLocOrigin loc (ScOrigin what NotNakedSc)
| otherwise
= loc
diff --git a/compiler/GHC/Tc/Solver/Monad.hs b/compiler/GHC/Tc/Solver/Monad.hs
index 67c90dcd80..b5cf81ad9d 100644
--- a/compiler/GHC/Tc/Solver/Monad.hs
+++ b/compiler/GHC/Tc/Solver/Monad.hs
@@ -672,8 +672,16 @@ lookupInInerts :: CtLoc -> TcPredType -> TcS (Maybe CtEvidence)
lookupInInerts loc pty
| ClassPred cls tys <- classifyPredType pty
= do { inerts <- getTcSInerts
- ; return (lookupSolvedDict inerts loc cls tys `mplus`
- fmap ctEvidence (lookupInertDict (inert_cans inerts) loc cls tys)) }
+ ; return $ -- Maybe monad
+ do { found_ev <-
+ lookupSolvedDict inerts loc cls tys `mplus`
+ fmap ctEvidence (lookupInertDict (inert_cans inerts) loc cls tys)
+ ; guard (not (prohibitedSuperClassSolve (ctEvLoc found_ev) loc))
+ -- We're about to "solve" the wanted we're looking up, so we
+ -- must make sure doing so wouldn't run afoul of
+ -- Note [Solving superclass constraints] in GHC.Tc.TyCl.Instance.
+ -- Forgetting this led to #20666.
+ ; return found_ev }}
| otherwise -- NB: No caching for equalities, IPs, holes, or errors
= return Nothing
@@ -783,7 +791,11 @@ data TcSEnv
}
---------------
-newtype TcS a = TcS { unTcS :: TcSEnv -> TcM a } deriving (Functor)
+newtype TcS a = TcS { unTcS :: TcSEnv -> TcM a }
+ deriving (Functor)
+
+instance MonadFix TcS where
+ mfix k = TcS $ \env -> mfix (\x -> unTcS (k x) env)
-- | Smart constructor for 'TcS', as describe in Note [The one-shot state
-- monad trick] in "GHC.Utils.Monad".
diff --git a/compiler/GHC/Tc/TyCl/Instance.hs b/compiler/GHC/Tc/TyCl/Instance.hs
index 6fda868642..3d9b5dd550 100644
--- a/compiler/GHC/Tc/TyCl/Instance.hs
+++ b/compiler/GHC/Tc/TyCl/Instance.hs
@@ -490,7 +490,7 @@ tcClsInstDecl (L loc (ClsInstDecl { cid_poly_ty = hs_ty, cid_binds = binds
do { dfun_ty <- tcHsClsInstType (InstDeclCtxt False) hs_ty
; let (tyvars, theta, clas, inst_tys) = tcSplitDFunTy dfun_ty
-- NB: tcHsClsInstType does checkValidInstance
- ; skol_info <- mkSkolemInfo InstSkol
+ ; skol_info <- mkSkolemInfo (mkClsInstSkol clas inst_tys)
; (subst, skol_tvs) <- tcInstSkolTyVars skol_info tyvars
; let tv_skol_prs = [ (tyVarName tv, skol_tv)
| (tv, skol_tv) <- tyvars `zip` skol_tvs ]
@@ -1228,19 +1228,14 @@ the default method Ids replete with their INLINE pragmas. Urk.
tcInstDecl2 :: InstInfo GhcRn -> TcM (LHsBinds GhcTc)
-- Returns a binding for the dfun
tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds })
- = recoverM (return emptyLHsBinds) $
- setSrcSpan loc $
- addErrCtxt (instDeclCtxt2 (idType dfun_id)) $
+ = recoverM (return emptyLHsBinds) $
+ setSrcSpan loc $
+ addErrCtxt (instDeclCtxt2 dfun_ty) $
do { -- Instantiate the instance decl with skolem constants
- ; skol_info <- mkSkolemInfo InstSkol
- ; (inst_tyvars, dfun_theta, inst_head) <- tcSkolDFunType skol_info dfun_id
+ (skol_info, inst_tyvars, dfun_theta, clas, inst_tys) <- tcSkolDFunType dfun_ty
; dfun_ev_vars <- newEvVars dfun_theta
- -- We instantiate the dfun_id with superSkolems.
- -- See Note [Subtle interaction of recursion and overlap]
- -- and Note [Binding when looking up instances]
- ; let (clas, inst_tys) = tcSplitDFunHead inst_head
- (class_tyvars, sc_theta, _, op_items) = classBigSig clas
+ ; let (class_tyvars, sc_theta, _, op_items) = classBigSig clas
sc_theta' = substTheta (zipTvSubst class_tyvars inst_tys) sc_theta
; traceTc "tcInstDecl2" (vcat [ppr inst_tyvars, ppr inst_tys, ppr dfun_theta, ppr sc_theta'])
@@ -1256,13 +1251,12 @@ tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds })
; (tclvl, (sc_meth_ids, sc_meth_binds, sc_meth_implics))
<- pushTcLevelM $
do { (sc_ids, sc_binds, sc_implics)
- <- tcSuperClasses dfun_id clas inst_tyvars dfun_ev_vars
- inst_tys dfun_ev_binds
- sc_theta'
+ <- tcSuperClasses skol_info dfun_id clas inst_tyvars
+ dfun_ev_vars dfun_ev_binds sc_theta'
-- Typecheck the methods
; (meth_ids, meth_binds, meth_implics)
- <- tcMethods dfun_id clas inst_tyvars dfun_ev_vars
+ <- tcMethods skol_info dfun_id clas inst_tyvars dfun_ev_vars
inst_tys dfun_ev_binds spec_inst_info
op_items ibinds
@@ -1277,7 +1271,7 @@ tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds })
, ic_given = dfun_ev_vars
, ic_wanted = mkImplicWC sc_meth_implics
, ic_binds = dfun_ev_binds_var
- , ic_info = InstSkol }
+ , ic_info = skol_info }
-- Create the result bindings
; self_dict <- newDict clas inst_tys
@@ -1335,6 +1329,7 @@ tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds })
}
where
dfun_id = instanceDFunId ispec
+ dfun_ty = idType dfun_id
loc = getSrcSpan dfun_id
addDFunPrags :: DFunId -> [Id] -> DFunId
@@ -1442,7 +1437,8 @@ Notice that
************************************************************************
-}
-tcSuperClasses :: DFunId -> Class -> [TcTyVar] -> [EvVar] -> [TcType]
+tcSuperClasses :: SkolemInfoAnon -> DFunId -> Class -> [TcTyVar]
+ -> [EvVar]
-> TcEvBinds
-> TcThetaType
-> TcM ([EvVar], LHsBinds GhcTc, Bag Implication)
@@ -1454,15 +1450,16 @@ tcSuperClasses :: DFunId -> Class -> [TcTyVar] -> [EvVar] -> [TcType]
-- See Note [Recursive superclasses] for why this is so hard!
-- In effect, we build a special-purpose solver for the first step
-- of solving each superclass constraint
-tcSuperClasses dfun_id cls tyvars dfun_evs inst_tys dfun_ev_binds sc_theta
+tcSuperClasses skol_info dfun_id cls tyvars dfun_evs dfun_ev_binds sc_theta
= do { (ids, binds, implics) <- mapAndUnzip3M tc_super (zip sc_theta [fIRST_TAG..])
; return (ids, listToBag binds, listToBag implics) }
where
loc = getSrcSpan dfun_id
- size = sizeTypes inst_tys
tc_super (sc_pred, n)
= do { (sc_implic, ev_binds_var, sc_ev_tm)
- <- checkInstConstraints $ emitWanted (ScOrigin size) sc_pred
+ <- checkInstConstraints skol_info $
+ emitWanted (ScOrigin IsClsInst NakedSc) sc_pred
+ -- ScOrigin IsClsInst True: see Note [Solving superclass constraints]
; sc_top_name <- newName (mkSuperDictAuxOcc n (getOccName cls))
; sc_ev_id <- newEvVar sc_pred
@@ -1484,10 +1481,10 @@ tcSuperClasses dfun_id cls tyvars dfun_evs inst_tys dfun_ev_binds sc_theta
; return (sc_top_id, L (noAnnSrcSpan loc) bind, sc_implic) }
-------------------
-checkInstConstraints :: TcM result
+checkInstConstraints :: SkolemInfoAnon -> TcM result
-> TcM (Implication, EvBindsVar, result)
-- See Note [Typechecking plan for instance declarations]
-checkInstConstraints thing_inside
+checkInstConstraints skol_info thing_inside
= do { (tclvl, wanted, result) <- pushLevelAndCaptureConstraints $
thing_inside
@@ -1496,7 +1493,7 @@ checkInstConstraints thing_inside
; let implic' = implic { ic_tclvl = tclvl
, ic_wanted = wanted
, ic_binds = ev_binds_var
- , ic_info = InstSkol }
+ , ic_info = skol_info }
; return (implic', ev_binds_var, result) }
@@ -1549,82 +1546,120 @@ definition. More precisely:
To achieve the Superclass Invariant, in a dfun definition we can
generate a guaranteed-non-bottom superclass witness from:
(sc1) one of the dictionary arguments itself (all non-bottom)
- (sc2) an immediate superclass of a smaller dictionary
+ (sc2) an immediate superclass of a non-bottom dictionary that is
+ /Paterson-smaller/ than the instance head
+ See Note [The PatersonSize of a type] in GHC.Tc.Utils.TcType
(sc3) a call of a dfun (always returns a dictionary constructor)
-The tricky case is (sc2). We proceed by induction on the size of
-the (type of) the dictionary, defined by GHC.Tc.Validity.sizeTypes.
-Let's suppose we are building a dictionary of size 3, and
-suppose the Superclass Invariant holds of smaller dictionaries.
-Then if we have a smaller dictionary, its immediate superclasses
-will be non-bottom by induction.
+The tricky case is (sc2). We proceed by induction on the size of the
+(type of) the dictionary, defined by GHC.Tc.Utils.TcType.pSizeType. Let's
+suppose we are building a dictionary of size 3 (the "head"), and suppose
+the Superclass Invariant holds of smaller dictionaries. Then if we have a
+smaller dictionary, its immediate superclasses will be non-bottom by
+induction.
+
+Why "Paterson-smaller"? See Note [Paterson conditions] in GHC.Tc.Validity.
+We want to be sure that the superclass dictionary is smaller /for any
+ground instatiation/ of the instance, so we need to account for type
+variables that occur more than once, and for type families (#20666). And
+that's exactly what the Paterson conditions check!
-What does "we have a smaller dictionary" mean? It might be
-one of the arguments of the instance, or one of its superclasses.
Here is an example, taken from CmmExpr:
class Ord r => UserOfRegs r a where ...
(i1) instance UserOfRegs r a => UserOfRegs r (Maybe a) where
(i2) instance (Ord r, UserOfRegs r CmmReg) => UserOfRegs r CmmExpr where
-For (i1) we can get the (Ord r) superclass by selection from (UserOfRegs r a),
-since it is smaller than the thing we are building (UserOfRegs r (Maybe a).
+For (i1) we can get the (Ord r) superclass by selection from
+(UserOfRegs r a), since it (i.e. UserOfRegs r a) is smaller than the
+thing we are building, namely (UserOfRegs r (Maybe a)).
-But for (i2) that isn't the case, so we must add an explicit, and
-perhaps surprising, (Ord r) argument to the instance declaration.
+But for (i2) that isn't the case: (UserOfRegs r CmmReg) is not smaller
+than the thing we are building (UserOfRegs r CmmExpr), so we can't use
+the superclasses of the former. Hence we must instead add an explicit,
+and perhaps surprising, (Ord r) argument to the instance declaration.
Here's another example from #6161:
- class Super a => Duper a where ...
- class Duper (Fam a) => Foo a where ...
-(i3) instance Foo a => Duper (Fam a) where ...
-(i4) instance Foo Float where ...
+ class Super a => Duper a where ...
+ class Duper (Maybe a) => Foo a where ...
+(i3) instance Foo a => Duper (Maybe a) where ...
+(i4) instance Foo Float where ...
It would be horribly wrong to define
- dfDuperFam :: Foo a -> Duper (Fam a) -- from (i3)
- dfDuperFam d = MkDuper (sc_sel1 (sc_sel2 d)) ...
+ dfDuperMaybe :: Foo a -> Duper (Maybe a) -- from (i3)
+ dfDuperMaybe d = MkDuper (sc_sel1 (sc_sel2 d)) ...
dfFooFloat :: Foo Float -- from (i4)
- dfFooFloat = MkFoo (dfDuperFam dfFooFloat) ...
-
-Now the Super superclass of Duper is definitely bottom!
-
-This won't happen because when processing (i3) we can use the
-superclasses of (Foo a), which is smaller, namely Duper (Fam a). But
-that is *not* smaller than the target so we can't take *its*
-superclasses. As a result the program is rightly rejected, unless you
-add (Super (Fam a)) to the context of (i3).
+ dfFooFloat = MkFoo (dfDuperMaybe dfFooFloat) ...
+
+Let's expand the RHS of dfFooFloat:
+ dfFooFloat = MkFoo (MkDuper (sc_sel1 (sc_sel2 dfFooFloat)) ...) ...
+That superclass argument to MkDuper is bottom!
+
+This program gets rejected because:
+* When processing (i3) we need to construct a dictionary for Super
+ (Maybe a), to put in the superclass field of (Duper (Maybe a)).
+* We /can/ use the superclasses of (Foo a), because the latter is
+ smaller than the head of the instance, namely Duper (Maybe a).
+* So we know (by (sc2)) that this Duper (Maybe a) dictionary is
+ non-bottom. But because (Duper (Maybe a)) is not smaller than the
+ instance head (Duper (Maybe a)), we can't take *its* superclasses.
+As a result the program is rightly rejected, unless you add
+(Super (Maybe a)) to the context of (i3).
+
+Wrinkle (W1):
+ (sc2) says we only get a non-bottom dict if the dict we are
+ selecting from is itself non-bottom. So in a superclass chain,
+ all the dictionaries in the chain must be non-bottom.
+ class C a => D3 a
+ class D2 a [[Maybe b]] => D1 a b
+ class D3 a => D2 a b
+ class C a => E a b
+ instance D1 a b => E a [b]
+ The instance needs the wanted superclass (C a). We can get it
+ by superclass selection from
+ D1 a b --> D2 a [[Maybe b]] --> D3 a --> C a
+ But on the way we go through the too-big (D2 a [[Maybe b]]), and
+ we don't know that is non-bottom.
Note [Solving superclass constraints]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-How do we ensure that every superclass witness is generated by
-one of (sc1) (sc2) or (sc3) in Note [Recursive superclasses].
+How do we ensure that every superclass witness in an instance declaration
+is generated by one of (sc1) (sc2) or (sc3) in Note [Recursive superclasses]?
Answer:
- * Superclass "wanted" constraints have CtOrigin of (ScOrigin size)
- where 'size' is the size of the instance declaration. e.g.
- class C a => D a where...
- instance blah => D [a] where ...
- The wanted superclass constraint for C [a] has origin
- ScOrigin size, where size = size( D [a] ).
+ * The "given" constraints of an instance decl have CtOrigin of
+ (GivenOrigin (InstSkol head_size)), where head_size is the
+ PatersonSize of the head of the instance declaration. E.g. in
+ instance D a => C [a]
+ the `[G] D a` constraint has a CtOrigin whose head_size is the
+ PatersonSize of (C [a]).
+
+ * When we make a superclass selection from a Given (transitively)
+ we give it a CtOrigin of (GivenSCOrigin skol_info sc_depth blocked).
+
+ The 'blocked :: Bool' flag says if the superclass can be used to
+ solve a superclass Wanted. The new superclass is blocked unless:
+
+ it is the superclass of an unblocked dictionary (wrinkle (W1)),
+ that is Paterson-smaller than the instance head.
+
+ This is implemented in GHC.Tc.Solver.Canonical.mk_strict_superclasses
+ (in the mk_given_loc helper function).
+
+ * Superclass "Wanted" constraints have CtOrigin of (ScOrigin NakedSc)
+ The 'NakedSc' says that this is a naked superclass Wanted; we must
+ be careful when solving it.
* (sc1) When we rewrite such a wanted constraint, it retains its
origin. But if we apply an instance declaration, we can set the
- origin to (ScOrigin infinity), thus lifting any restrictions by
- making prohibitedSuperClassSolve return False.
+ origin to (ScOrigin NotNakedSc), thus lifting any restrictions by
+ making prohibitedSuperClassSolve return False. This happens
+ in GHC.Tc.Solver.Interact.checkInstanceOK.
* (sc2) ScOrigin wanted constraints can't be solved from a
superclass selection, except at a smaller type. This test is
- implemented by GHC.Tc.Solver.Interact.prohibitedSuperClassSolve
-
- * The "given" constraints of an instance decl have CtOrigin
- GivenOrigin InstSkol.
-
- * When we make a superclass selection from InstSkol we use
- a CtOrigin of (InstSCOrigin size), where 'size' is the size of
- the constraint whose superclass we are taking. And similarly
- when taking the superclass of an InstSCOrigin. This is implemented
- in GHC.Tc.Solver.Canonical.mk_strict_superclasses (in the
- mk_given_loc helper function).
+ implemented by GHC.Tc.Solver.InertSet.prohibitedSuperClassSolve
Note [Silent superclass arguments] (historical interest only)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1697,7 +1732,7 @@ tcMethod
- Use tcValBinds to do the checking
-}
-tcMethods :: DFunId -> Class
+tcMethods :: SkolemInfoAnon -> DFunId -> Class
-> [TcTyVar] -> [EvVar]
-> [TcType]
-> TcEvBinds
@@ -1707,7 +1742,7 @@ tcMethods :: DFunId -> Class
-> TcM ([Id], LHsBinds GhcTc, Bag Implication)
-- The returned inst_meth_ids all have types starting
-- forall tvs. theta => ...
-tcMethods dfun_id clas tyvars dfun_ev_vars inst_tys
+tcMethods skol_info dfun_id clas tyvars dfun_ev_vars inst_tys
dfun_ev_binds (spec_inst_prags, prag_fn) op_items
(InstBindings { ib_binds = binds
, ib_tyvars = lexical_tvs
@@ -1740,10 +1775,10 @@ tcMethods dfun_id clas tyvars dfun_ev_vars inst_tys
tc_item :: ClassOpItem -> TcM (Id, LHsBind GhcTc, Maybe Implication)
tc_item (sel_id, dm_info)
| Just (user_bind, bndr_loc, prags) <- findMethodBind (idName sel_id) binds prag_fn
- = tcMethodBody clas tyvars dfun_ev_vars inst_tys
- dfun_ev_binds is_derived hs_sig_fn
- spec_inst_prags prags
- sel_id user_bind bndr_loc
+ = tcMethodBody skol_info clas tyvars dfun_ev_vars inst_tys
+ dfun_ev_binds is_derived hs_sig_fn
+ spec_inst_prags prags
+ sel_id user_bind bndr_loc
| otherwise
= do { traceTc "tc_def" (ppr sel_id)
; tc_default sel_id dm_info }
@@ -1754,7 +1789,7 @@ tcMethods dfun_id clas tyvars dfun_ev_vars inst_tys
tc_default sel_id (Just (dm_name, _))
= do { (meth_bind, inline_prags) <- mkDefMethBind inst_loc dfun_id clas sel_id dm_name
- ; tcMethodBody clas tyvars dfun_ev_vars inst_tys
+ ; tcMethodBody skol_info clas tyvars dfun_ev_vars inst_tys
dfun_ev_binds is_derived hs_sig_fn
spec_inst_prags inline_prags
sel_id meth_bind inst_loc }
@@ -1872,13 +1907,14 @@ Instead, we take the much simpler approach of always disabling
-}
------------------------
-tcMethodBody :: Class -> [TcTyVar] -> [EvVar] -> [TcType]
+tcMethodBody :: SkolemInfoAnon
+ -> Class -> [TcTyVar] -> [EvVar] -> [TcType]
-> TcEvBinds -> Bool
-> HsSigFun
-> [LTcSpecPrag] -> [LSig GhcRn]
-> Id -> LHsBind GhcRn -> SrcSpan
-> TcM (TcId, LHsBind GhcTc, Maybe Implication)
-tcMethodBody clas tyvars dfun_ev_vars inst_tys
+tcMethodBody skol_info clas tyvars dfun_ev_vars inst_tys
dfun_ev_binds is_derived
sig_fn spec_inst_prags prags
sel_id (L bind_loc meth_bind) bndr_loc
@@ -1896,7 +1932,7 @@ tcMethodBody clas tyvars dfun_ev_vars inst_tys
-- taking instance signature into account might change the type of
-- the local_meth_id
; (meth_implic, ev_binds_var, tc_bind)
- <- checkInstConstraints $
+ <- checkInstConstraints skol_info $
tcMethodBodyHelp sig_fn sel_id local_meth_id (L bind_loc lm_bind)
; global_meth_id <- addInlinePrags global_meth_id prags
@@ -2353,9 +2389,9 @@ instDeclCtxt1 hs_inst_ty
instDeclCtxt2 :: Type -> SDoc
instDeclCtxt2 dfun_ty
- = inst_decl_ctxt (ppr (mkClassPred cls tys))
+ = inst_decl_ctxt (ppr head_ty)
where
- (_,_,cls,tys) = tcSplitDFunTy dfun_ty
+ (_,_,head_ty) = tcSplitQuantPredTy dfun_ty
inst_decl_ctxt :: SDoc -> SDoc
inst_decl_ctxt doc = hang (text "In the instance declaration for")
diff --git a/compiler/GHC/Tc/Types/Constraint.hs b/compiler/GHC/Tc/Types/Constraint.hs
index 2fea177885..0623acd3d5 100644
--- a/compiler/GHC/Tc/Types/Constraint.hs
+++ b/compiler/GHC/Tc/Types/Constraint.hs
@@ -1690,7 +1690,7 @@ checkSkolInfoAnon sk1 sk2 = go sk1 sk2
go (DerivSkol pred1) (DerivSkol pred2) = pred1 `tcEqType` pred2
go (TyConSkol f1 n1) (TyConSkol f2 n2) = f1==f2 && n1==n2
go (DataConSkol n1) (DataConSkol n2) = n1==n2
- go InstSkol InstSkol = True
+ go (InstSkol {}) (InstSkol {}) = True
go FamInstSkol FamInstSkol = True
go BracketSkol BracketSkol = True
go (RuleSkol n1) (RuleSkol n2) = n1==n2
@@ -1700,7 +1700,6 @@ checkSkolInfoAnon sk1 sk2 = go sk1 sk2
and (zipWith eq_pr ids1 ids2)
go (UnifyForAllSkol t1) (UnifyForAllSkol t2) = t1 `tcEqType` t2
go ReifySkol ReifySkol = True
- go QuantCtxtSkol QuantCtxtSkol = True
go RuntimeUnkSkol RuntimeUnkSkol = True
go ArrowReboundIfSkol ArrowReboundIfSkol = True
go (UnkSkol _) (UnkSkol _) = True
@@ -1716,7 +1715,7 @@ checkSkolInfoAnon sk1 sk2 = go sk1 sk2
-- in tcConDecl for MkT we'll have a SkolemInfo in the implication of
-- DataConSkol, but 'a' will have SkolemInfo of FamInstSkol
- go FamInstSkol InstSkol = True
+ go FamInstSkol (InstSkol {}) = True
-- In instance C (T a) where { type F (T a) b = ... }
-- we have 'a' with SkolemInfo InstSkol, but we make an implication wi
-- SkolemInfo of FamInstSkol. Very like the ConDecl/TyConSkol case
diff --git a/compiler/GHC/Tc/Types/Origin.hs b/compiler/GHC/Tc/Types/Origin.hs
index 72ed58b041..4a40528f1f 100644
--- a/compiler/GHC/Tc/Types/Origin.hs
+++ b/compiler/GHC/Tc/Types/Origin.hs
@@ -13,7 +13,7 @@ module GHC.Tc.Types.Origin (
-- * SkolemInfo
SkolemInfo(..), SkolemInfoAnon(..), mkSkolemInfo, getSkolemInfo, pprSigSkolInfo, pprSkolInfo,
- unkSkol, unkSkolAnon,
+ unkSkol, unkSkolAnon, mkClsInstSkol,
-- * CtOrigin
CtOrigin(..), exprCtOrigin, lexprCtOrigin, matchesCtOrigin, grhssCtOrigin,
@@ -29,6 +29,7 @@ module GHC.Tc.Types.Origin (
FixedRuntimeRepOrigin(..), FixedRuntimeRepContext(..),
pprFixedRuntimeRepContext,
StmtOrigin(..), RepPolyFun(..), ArgPos(..),
+ ClsInstOrQC(..), NakedScFlag(..),
-- * Arrow command origin
FRRArrowContext(..), pprFRRArrowContext,
@@ -45,6 +46,7 @@ import GHC.Hs
import GHC.Core.DataCon
import GHC.Core.ConLike
import GHC.Core.TyCon
+import GHC.Core.Class
import GHC.Core.InstEnv
import GHC.Core.PatSyn
import GHC.Core.Multiplicity ( scaledThing )
@@ -210,8 +212,9 @@ isSigMaybe _ = Nothing
-- same place in a single report.
data SkolemInfo
= SkolemInfo
- Unique -- ^ used to common up skolem variables bound at the same location (only used in pprSkols)
- SkolemInfoAnon -- ^ the information about the origin of the skolem type variable
+ Unique -- ^ The Unique is used to common up skolem variables bound
+ -- at the same location (only used in pprSkols)
+ SkolemInfoAnon -- ^ The information about the origin of the skolem type variable
instance Uniquable SkolemInfo where
getUnique (SkolemInfo u _) = u
@@ -248,7 +251,9 @@ data SkolemInfoAnon
| DerivSkol Type -- Bound by a 'deriving' clause;
-- the type is the instance we are trying to derive
- | InstSkol -- Bound at an instance decl
+ | InstSkol -- Bound at an instance decl, or quantified constraint
+ ClsInstOrQC -- Whether class instance or quantified constraint
+ PatersonSize -- Head has the given PatersonSize
| FamInstSkol -- Bound at a family instance decl
| PatSkol -- An existential type variable bound by a pattern for
@@ -280,9 +285,6 @@ data SkolemInfoAnon
| ReifySkol -- Bound during Template Haskell reification
- | QuantCtxtSkol -- Quantified context, e.g.
- -- f :: forall c. (forall a. c a => c [a]) => blah
-
| RuntimeUnkSkol -- Runtime skolem from the GHCi debugger #14628
| ArrowReboundIfSkol -- Bound by the expected type of the rebound arrow ifThenElse command.
@@ -312,6 +314,8 @@ mkSkolemInfo sk_anon = do
getSkolemInfo :: SkolemInfo -> SkolemInfoAnon
getSkolemInfo (SkolemInfo _ skol_anon) = skol_anon
+mkClsInstSkol :: Class -> [Type] -> SkolemInfoAnon
+mkClsInstSkol cls tys = InstSkol IsClsInst (pSizeClassPred cls tys)
instance Outputable SkolemInfo where
ppr (SkolemInfo _ sk_info ) = ppr sk_info
@@ -327,7 +331,10 @@ pprSkolInfo (ForAllSkol tvs) = text "an explicit forall" <+> ppr tvs
pprSkolInfo (IPSkol ips) = text "the implicit-parameter binding" <> plural ips <+> text "for"
<+> pprWithCommas ppr ips
pprSkolInfo (DerivSkol pred) = text "the deriving clause for" <+> quotes (ppr pred)
-pprSkolInfo InstSkol = text "the instance declaration"
+pprSkolInfo (InstSkol IsClsInst sz) = vcat [ text "the instance declaration"
+ , whenPprDebug (braces (ppr sz)) ]
+pprSkolInfo (InstSkol (IsQC {}) sz) = vcat [ text "a quantified context"
+ , whenPprDebug (braces (ppr sz)) ]
pprSkolInfo FamInstSkol = text "a family instance declaration"
pprSkolInfo BracketSkol = text "a Template Haskell bracket"
pprSkolInfo (RuleSkol name) = text "the RULE" <+> pprRuleName name
@@ -341,7 +348,6 @@ pprSkolInfo (TyConSkol flav name) = text "the" <+> ppr flav <+> text "declaratio
pprSkolInfo (DataConSkol name) = text "the type signature for" <+> quotes (ppr name)
pprSkolInfo ReifySkol = text "the type being reified"
-pprSkolInfo (QuantCtxtSkol {}) = text "a quantified context"
pprSkolInfo RuntimeUnkSkol = text "Unknown type from GHCi runtime"
pprSkolInfo ArrowReboundIfSkol = text "the expected type of a rebound if-then-else command"
@@ -450,39 +456,25 @@ data CtOrigin
-- 'SkolemInfo' inside gives more information.
GivenOrigin SkolemInfoAnon
- -- The following are other origins for given constraints that cannot produce
- -- new skolems -- hence no SkolemInfo.
-
- -- | 'InstSCOrigin' is used for a Given constraint obtained by superclass selection
+ -- | 'GivenSCOrigin' is used for a Given constraint obtained by superclass selection
-- from the context of an instance declaration. E.g.
-- instance @(Foo a, Bar a) => C [a]@ where ...
-- When typechecking the instance decl itself, including producing evidence
-- for the superclasses of @C@, the superclasses of @(Foo a)@ and @(Bar a)@ will
- -- have 'InstSCOrigin' origin.
- | InstSCOrigin ScDepth -- ^ The number of superclass selections necessary to
- -- get this constraint; see Note [Replacement vs keeping]
- -- in GHC.Tc.Solver.Interact
- TypeSize -- ^ If @(C ty1 .. tyn)@ is the largest class from
- -- which we made a superclass selection in the chain,
- -- then @TypeSize = sizeTypes [ty1, .., tyn]@
- -- See Note [Solving superclass constraints] in GHC.Tc.TyCl.Instance
-
- -- | 'OtherSCOrigin' is used for a Given constraint obtained by superclass
- -- selection from a constraint /other than/ the context of an instance
- -- declaration. (For the latter we use 'InstSCOrigin'.) E.g.
- -- f :: Foo a => blah
- -- f = e
- -- When typechecking body of 'f', the superclasses of the Given (Foo a)
- -- will have 'OtherSCOrigin'.
- --
- -- Needed for Note [Replacement vs keeping] in GHC.Tc.Solver.Interact.
- | OtherSCOrigin ScDepth -- ^ The number of superclass selections necessary to
- -- get this constraint
- SkolemInfoAnon
- -- ^ Where the sub-class constraint arose from
- -- (used only for printing)
+ -- have 'GivenSCOrigin' origin.
+ | GivenSCOrigin
+ SkolemInfoAnon -- ^ Just like GivenOrigin
+
+ ScDepth -- ^ The number of superclass selections necessary to
+ -- get this constraint; see Note [Replacement vs keeping]
+ -- in GHC.Tc.Solver.Interact
- -- All the others are for *wanted* constraints
+ Bool -- ^ True => "blocked": cannot use this to solve naked superclass Wanteds
+ -- i.e. ones with (ScOrigin _ NakedSc)
+ -- False => can use this to solve all Wanted constraints
+ -- See Note [Solving superclass constraints] in GHC.Tc.TyCl.Instance
+
+ ----------- Below here, all are Origins for Wanted constraints ------------
| OccurrenceOf Name -- Occurrence of an overloaded identifier
| OccurrenceOfRecSel RdrName -- Occurrence of a record selector
@@ -531,11 +523,10 @@ data CtOrigin
| ViewPatOrigin
-- | 'ScOrigin' is used only for the Wanted constraints for the
- -- superclasses of an instance declaration.
- -- If the instance head is @C ty1 .. tyn@
- -- then @TypeSize = sizeTypes [ty1, .., tyn]@
- -- See Note [Solving superclass constraints] in GHC.Tc.TyCl.Instance
- | ScOrigin TypeSize
+ -- superclasses of an instance declaration.
+ | ScOrigin
+ ClsInstOrQC -- Whether class instance or quantified constraint
+ NakedScFlag
| DerivClauseOrigin -- Typechecking a deriving clause (as opposed to
-- standalone deriving).
@@ -604,6 +595,7 @@ data CtOrigin
| CycleBreakerOrigin
CtOrigin -- origin of the original constraint
+
-- See Detail (7) of Note [Type equality cycles] in GHC.Tc.Solver.Canonical
| FRROrigin
FixedRuntimeRepOrigin
@@ -619,11 +611,25 @@ data CtOrigin
Type -- the instantiated type of the method
| AmbiguityCheckOrigin UserTypeCtxt
+
-- | The number of superclass selections needed to get this Given.
-- If @d :: C ty@ has @ScDepth=2@, then the evidence @d@ will look
-- like @sc_sel (sc_sel dg)@, where @dg@ is a Given.
type ScDepth = Int
+data ClsInstOrQC = IsClsInst
+ | IsQC CtOrigin
+
+data NakedScFlag = NakedSc | NotNakedSc
+ -- The NakedScFlag affects only GHC.Tc.Solver.InertSet.prohibitedSuperClassSolve
+ -- * For the original superclass constraints we use (ScOrigin _ NakedSc)
+ -- * But after using an instance declaration we use (ScOrigin _ NotNakedSc)
+ -- See Note [Solving superclass constraints] in GHC.Tc.TyCl.Instance
+
+instance Outputable NakedScFlag where
+ ppr NakedSc = text "NakedSc"
+ ppr NotNakedSc = text "NotNakedSc"
+
-- An origin is visible if the place where the constraint arises is manifest
-- in user code. Currently, all origins are visible except for invisible
-- TypeEqOrigins. This is used when choosing which error of
@@ -640,11 +646,10 @@ toInvisibleOrigin orig@(TypeEqOrigin {}) = orig { uo_visible = False }
toInvisibleOrigin orig = orig
isGivenOrigin :: CtOrigin -> Bool
-isGivenOrigin (GivenOrigin {}) = True
-isGivenOrigin (InstSCOrigin {}) = True
-isGivenOrigin (OtherSCOrigin {}) = True
-isGivenOrigin (CycleBreakerOrigin o) = isGivenOrigin o
-isGivenOrigin _ = False
+isGivenOrigin (GivenOrigin {}) = True
+isGivenOrigin (GivenSCOrigin {}) = True
+isGivenOrigin (CycleBreakerOrigin o) = isGivenOrigin o
+isGivenOrigin _ = False
-- See Note [Suppressing confusing errors] in GHC.Tc.Errors
isWantedWantedFunDepOrigin :: CtOrigin -> Bool
@@ -731,9 +736,12 @@ lGRHSCtOrigin _ = Shouldn'tHappenOrigin "multi-way GRHS"
pprCtOrigin :: CtOrigin -> SDoc
-- "arising from ..."
-pprCtOrigin (GivenOrigin sk) = ctoHerald <+> ppr sk
-pprCtOrigin (InstSCOrigin {}) = ctoHerald <+> pprSkolInfo InstSkol -- keep output in sync
-pprCtOrigin (OtherSCOrigin _ si) = ctoHerald <+> pprSkolInfo si
+pprCtOrigin (GivenOrigin sk)
+ = ctoHerald <+> ppr sk
+
+pprCtOrigin (GivenSCOrigin sk d blk)
+ = vcat [ ctoHerald <+> pprSkolInfo sk
+ , whenPprDebug (braces (text "given-sc:" <+> ppr d <> comma <> ppr blk)) ]
pprCtOrigin (SpecPragOrigin ctxt)
= case ctxt of
@@ -817,9 +825,6 @@ pprCtOrigin (InstProvidedOrigin mod cls_inst)
pprCtOrigin (CycleBreakerOrigin orig)
= pprCtOrigin orig
-pprCtOrigin (FRROrigin {})
- = ctoHerald <+> text "a representation-polymorphism check"
-
pprCtOrigin (WantedSuperclassOrigin subclass_pred subclass_orig)
= sep [ ctoHerald <+> text "a superclass required to satisfy" <+> quotes (ppr subclass_pred) <> comma
, pprCtOrigin subclass_orig ]
@@ -836,6 +841,15 @@ pprCtOrigin (AmbiguityCheckOrigin ctxt)
= ctoHerald <+> text "a type ambiguity check for" $$
pprUserTypeCtxt ctxt
+pprCtOrigin (ScOrigin IsClsInst nkd)
+ = vcat [ ctoHerald <+> text "the superclasses of an instance declaration"
+ , whenPprDebug (braces (text "sc-origin:" <> ppr nkd)) ]
+
+pprCtOrigin (ScOrigin (IsQC orig) nkd)
+ = vcat [ ctoHerald <+> text "the head of a quantified constraint"
+ , whenPprDebug (braces (text "sc-origin:" <> ppr nkd))
+ , pprCtOrigin orig ]
+
pprCtOrigin simple_origin
= ctoHerald <+> pprCtO simple_origin
@@ -859,8 +873,8 @@ pprCtO (HasFieldOrigin f) = hsep [text "selecting the field", quotes (ppr f)]
pprCtO AssocFamPatOrigin = text "the LHS of a family instance"
pprCtO TupleOrigin = text "a tuple"
pprCtO NegateOrigin = text "a use of syntactic negation"
-pprCtO (ScOrigin n) = text "the superclasses of an instance declaration"
- <> whenPprDebug (parens (ppr n))
+pprCtO (ScOrigin IsClsInst _) = text "the superclasses of an instance declaration"
+pprCtO (ScOrigin (IsQC {}) _) = text "the head of a quantified constraint"
pprCtO DerivClauseOrigin = text "the 'deriving' clause of a data type declaration"
pprCtO StandAloneDerivOrigin = text "a 'deriving' declaration"
pprCtO DefaultOrigin = text "a 'default' declaration"
@@ -884,8 +898,7 @@ pprCtO BracketOrigin = text "a quotation bracket"
-- get here via callStackOriginFS, when doing ambiguity checks
-- A bit silly, but no great harm
pprCtO (GivenOrigin {}) = text "a given constraint"
-pprCtO (InstSCOrigin {}) = text "the superclass of an instance constraint"
-pprCtO (OtherSCOrigin {}) = text "the superclass of a given constraint"
+pprCtO (GivenSCOrigin {}) = text "the superclass of a given constraint"
pprCtO (SpecPragOrigin {}) = text "a SPECIALISE pragma"
pprCtO (FunDepOrigin1 {}) = text "a functional dependency"
pprCtO (FunDepOrigin2 {}) = text "a functional dependency"
diff --git a/compiler/GHC/Tc/Utils/Backpack.hs b/compiler/GHC/Tc/Utils/Backpack.hs
index a73c01c90f..f11b900d6e 100644
--- a/compiler/GHC/Tc/Utils/Backpack.hs
+++ b/compiler/GHC/Tc/Utils/Backpack.hs
@@ -27,7 +27,6 @@ import GHC.Types.Fixity (defaultFixity)
import GHC.Types.Fixity.Env
import GHC.Types.TypeEnv
import GHC.Types.Name.Reader
-import GHC.Types.Id
import GHC.Types.Name
import GHC.Types.Name.Env
import GHC.Types.Name.Set
@@ -35,6 +34,7 @@ import GHC.Types.Avail
import GHC.Types.SrcLoc
import GHC.Types.SourceFile
import GHC.Types.Var
+import GHC.Types.Id( idType )
import GHC.Types.Unique.DSet
import GHC.Types.Name.Shape
import GHC.Types.PkgQual
@@ -62,8 +62,6 @@ import GHC.Hs
import GHC.Core.InstEnv
import GHC.Core.FamInstEnv
-import GHC.Core.Type
-import GHC.Core.Multiplicity
import GHC.IfaceToCore
import GHC.Iface.Load
@@ -221,32 +219,23 @@ checkHsigIface tcg_env gr sig_iface
-- (we might conclude the module exports an instance when it doesn't, see
-- #9422), but we will never refuse to compile something.
check_inst :: ClsInst -> TcM ()
-check_inst sig_inst = do
+check_inst sig_inst@(ClsInst { is_dfun = dfun_id }) = do
-- TODO: This could be very well generalized to support instance
-- declarations in boot files.
tcg_env <- getGblEnv
-- NB: Have to tug on the interface, not necessarily
-- tugged... but it didn't work?
mapM_ tcLookupImported_maybe (nameSetElemsStable (orphNamesOfClsInst sig_inst))
+
-- Based off of 'simplifyDeriv'
- let ty = idType (instanceDFunId sig_inst)
- -- Based off of tcSplitDFunTy
- (tvs, theta, pred) =
- case tcSplitForAllInvisTyVars ty of { (tvs, rho) ->
- case splitFunTys rho of { (theta, pred) ->
- (tvs, theta, pred) }}
- origin = InstProvidedOrigin (tcg_semantic_mod tcg_env) sig_inst
- skol_info <- mkSkolemInfo InstSkol
- (skol_subst, tvs_skols) <- tcInstSkolTyVars skol_info tvs -- Skolemize
+ let origin = InstProvidedOrigin (tcg_semantic_mod tcg_env) sig_inst
+ (skol_info, tvs_skols, inst_theta, cls, inst_tys) <- tcSkolDFunType (idType dfun_id)
(tclvl,cts) <- pushTcLevelM $ do
- wanted <- newWanted origin
- (Just TypeLevel)
- (substTy skol_subst pred)
- givens <- forM theta $ \given -> do
+ wanted <- newWanted origin (Just TypeLevel) (mkClassPred cls inst_tys)
+ givens <- forM inst_theta $ \given -> do
loc <- getCtLocM origin (Just TypeLevel)
- let given_pred = substTy skol_subst (scaledThing given)
- new_ev <- newEvVar given_pred
- return CtGiven { ctev_pred = given_pred
+ new_ev <- newEvVar given
+ return CtGiven { ctev_pred = given
-- Doesn't matter, make something up
, ctev_evar = new_ev
, ctev_loc = loc
@@ -254,7 +243,7 @@ check_inst sig_inst = do
return $ wanted : givens
unsolved <- simplifyWantedsTcM cts
- (implic, _) <- buildImplicationFor tclvl (getSkolemInfo skol_info) tvs_skols [] unsolved
+ (implic, _) <- buildImplicationFor tclvl skol_info tvs_skols [] unsolved
reportAllUnsolved (mkImplicWC implic)
-- | For a module @modname@ of type 'HscSource', determine the list
diff --git a/compiler/GHC/Tc/Utils/Instantiate.hs b/compiler/GHC/Tc/Utils/Instantiate.hs
index 0b6b519028..b8249bc363 100644
--- a/compiler/GHC/Tc/Utils/Instantiate.hs
+++ b/compiler/GHC/Tc/Utils/Instantiate.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleContexts, RecursiveDo #-}
{-# LANGUAGE DisambiguateRecordFields #-}
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
@@ -446,12 +446,24 @@ tcInstTypeBndrs poly_ty
; return (subst', Bndr tv' spec) }
--------------------------
-tcSkolDFunType :: SkolemInfo -> DFunId -> TcM ([TcTyVar], TcThetaType, TcType)
+tcSkolDFunType :: Type -> TcM (SkolemInfoAnon, [TcTyVar], TcThetaType, Class, [TcType])
-- Instantiate a type signature with skolem constants.
-- This freshens the names, but no need to do so
-tcSkolDFunType skol_info dfun
- = do { (tv_prs, theta, tau) <- tcInstType (tcInstSuperSkolTyVars skol_info) dfun
- ; return (map snd tv_prs, theta, tau) }
+tcSkolDFunType dfun_ty
+ = do { let (tvs, theta, cls, tys) = tcSplitDFunTy dfun_ty
+
+ -- rec {..}: see Note [Keeping SkolemInfo inside a SkolemTv]
+ -- in GHC.Tc.Utils.TcType
+ ; rec { skol_info <- mkSkolemInfo skol_info_anon
+ ; (subst, inst_tvs) <- tcInstSuperSkolTyVars skol_info tvs
+ -- We instantiate the dfun_tyd with superSkolems.
+ -- See Note [Subtle interaction of recursion and overlap]
+ -- and Note [Binding when looking up instances]
+ ; let inst_tys = substTys subst tys
+ skol_info_anon = mkClsInstSkol cls inst_tys }
+
+ ; let inst_theta = substTheta subst theta
+ ; return (skol_info_anon, inst_tvs, inst_theta, cls, inst_tys) }
tcSuperSkolTyVars :: TcLevel -> SkolemInfo -> [TyVar] -> (Subst, [TcTyVar])
-- Make skolem constants, but do *not* give them new names, as above
@@ -483,7 +495,9 @@ tcInstSkolTyVarsX skol_info = tcInstSkolTyVarsPushLevel skol_info False
tcInstSuperSkolTyVars :: SkolemInfo -> [TyVar] -> TcM (Subst, [TcTyVar])
-- See Note [Skolemising type variables]
-- This version freshens the names and creates "super skolems";
--- see comments around superSkolemTv.
+-- see comments around superSkolemTv.
+-- Must be lazy in skol_info:
+-- see Note [Keeping SkolemInfo inside a SkolemTv] in GHC.Tc.Utils.TcType
tcInstSuperSkolTyVars skol_info = tcInstSuperSkolTyVarsX skol_info emptySubst
tcInstSuperSkolTyVarsX :: SkolemInfo -> Subst -> [TyVar] -> TcM (Subst, [TcTyVar])
diff --git a/compiler/GHC/Tc/Utils/TcMType.hs b/compiler/GHC/Tc/Utils/TcMType.hs
index 5824c3e7f6..89614378cd 100644
--- a/compiler/GHC/Tc/Utils/TcMType.hs
+++ b/compiler/GHC/Tc/Utils/TcMType.hs
@@ -2579,10 +2579,10 @@ zonkTidyOrigin env (GivenOrigin skol_info)
= do { skol_info1 <- zonkSkolemInfoAnon skol_info
; let skol_info2 = tidySkolemInfoAnon env skol_info1
; return (env, GivenOrigin skol_info2) }
-zonkTidyOrigin env (OtherSCOrigin sc_depth skol_info)
+zonkTidyOrigin env (GivenSCOrigin skol_info sc_depth blocked)
= do { skol_info1 <- zonkSkolemInfoAnon skol_info
; let skol_info2 = tidySkolemInfoAnon env skol_info1
- ; return (env, OtherSCOrigin sc_depth skol_info2) }
+ ; return (env, GivenSCOrigin skol_info2 sc_depth blocked) }
zonkTidyOrigin env orig@(TypeEqOrigin { uo_actual = act
, uo_expected = exp })
= do { (env1, act') <- zonkTidyTcType env act
diff --git a/compiler/GHC/Tc/Utils/TcType.hs b/compiler/GHC/Tc/Utils/TcType.hs
index 28894d68ed..dc6bbe746b 100644
--- a/compiler/GHC/Tc/Utils/TcType.hs
+++ b/compiler/GHC/Tc/Utils/TcType.hs
@@ -86,6 +86,7 @@ module GHC.Tc.Utils.TcType (
checkValidClsArgs, hasTyVarHead,
isRigidTy,
+
-- Re-exported from GHC.Core.TyCo.Compare
-- mainly just for back-compat reasons
eqType, eqTypes, nonDetCmpType, nonDetCmpTypes, eqTypeX,
@@ -130,6 +131,18 @@ module GHC.Tc.Utils.TcType (
isFunPtrTy, -- :: Type -> Bool
tcSplitIOType_maybe, -- :: Type -> Maybe Type
+ ---------------------------------
+ -- Patersons sizes
+ PatersonSize(..), PatersonSizeFailure(..),
+ ltPatersonSize,
+ pSizeZero, pSizeOne,
+ pSizeType, pSizeTypeX, pSizeTypes,
+ pSizeClassPred, pSizeClassPredX,
+ pSizeTyConApp,
+ noMoreTyVars, allDistinctTyVars,
+ TypeSize, sizeType, sizeTypes, scopedSort,
+ isTerminatingClass, isStuckTypeFamily,
+
--------------------------------
-- Reexported from Kind
Kind, liftedTypeKind, constraintKind,
@@ -152,7 +165,7 @@ module GHC.Tc.Utils.TcType (
isClassPred, isEqPrimPred, isIPLikePred, isEqPred, isEqPredClass,
mkClassPred,
- tcSplitDFunTy, tcSplitDFunHead, tcSplitMethodTy,
+ tcSplitQuantPredTy, tcSplitDFunTy, tcSplitDFunHead, tcSplitMethodTy,
isRuntimeRepVar, isFixedRuntimeRepKind,
isVisiblePiTyBinder, isInvisiblePiTyBinder,
@@ -192,8 +205,6 @@ module GHC.Tc.Utils.TcType (
pprTheta, pprParendTheta, pprThetaArrowTy, pprClassPred,
pprTCvBndr, pprTCvBndrs,
- TypeSize, sizeType, sizeTypes, scopedSort,
-
---------------------------------
-- argument visibility
tcTyConVisibilities, isNextTyConArgVisible, isNextArgVisible
@@ -244,7 +255,7 @@ import qualified GHC.LanguageExtensions as LangExt
import Data.IORef
import Data.List.NonEmpty( NonEmpty(..) )
-import Data.List ( partition )
+import Data.List ( partition, nub, (\\) )
import GHC.Generics ( Generic )
@@ -585,13 +596,32 @@ vanillaSkolemTv for a TyVar.
But ultimately I want to separate Type from TcType, and in that case
we would need to enforce the separation.
+
+Note [Keeping SkolemInfo inside a SkolemTv]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+A SkolemTv contains a SkolemInfo, which describes the binding side of that
+TcTyVar. This is very convenient to a consumer of a SkolemTv, but it is
+a bit awkward for the /producer/. Why? Because sometimes we can't produce
+the SkolemInfo until we have the TcTyVars!
+
+Example: in `GHC.Tc.Utils.Unify.tcTopSkolemise` we create SkolemTvs whose
+`SkolemInfo` is `SigSkol`, whose arguments in turn mention the newly-created
+SkolemTvs. So we a RecrusiveDo idiom, like this:
+
+ rec { (wrap, tv_prs, given, rho_ty) <- skolemise skol_info expected_ty
+ ; skol_info <- mkSkolemInfo (SigSkol ctxt expected_ty tv_prs) }
+
+Note that the `skol_info` can't be created until we have the `tv_prs` returned
+by `skolemise`. Note also that `skolemise` had better be lazy in `skol_info`.
+
+All uses of this idiom should be flagged with a reference to this Note.
-}
-- A TyVarDetails is inside a TyVar
-- See Note [TyVars and TcTyVars during type checking]
data TcTyVarDetails
= SkolemTv -- A skolem
- SkolemInfo
+ SkolemInfo -- See Note [Keeping SkolemInfo inside a SkolemTv]
TcLevel -- Level of the implication that binds it
-- See GHC.Tc.Utils.Unify Note [Deeper level on the left] for
-- how this level number is used
@@ -1581,20 +1611,23 @@ tcIsTyVarTy (TyVarTy _) = True
tcIsTyVarTy _ = False
-----------------------
-tcSplitDFunTy :: Type -> ([TyVar], [Type], Class, [Type])
--- Split the type of a dictionary function
--- We don't use tcSplitSigmaTy, because a DFun may (with NDP)
--- have non-Pred arguments, such as
--- df :: forall m. (forall b. Eq b => Eq (m b)) -> C m
---
--- Also NB splitFunTys, not tcSplitFunTys;
+tcSplitQuantPredTy :: Type -> ([TyVar], [Type], PredType)
+-- Split up the type of a quantified predicate
+-- forall tys, theta => head
+-- NB splitFunTys, not tcSplitFunTys;
-- the latter specifically stops at PredTy arguments,
-- and we don't want to do that here
-tcSplitDFunTy ty
+tcSplitQuantPredTy ty
= case tcSplitForAllInvisTyVars ty of { (tvs, rho) ->
- case splitFunTys rho of { (theta, tau) ->
- case tcSplitDFunHead tau of { (clas, tys) ->
- (tvs, map scaledThing theta, clas, tys) }}}
+ case splitFunTys rho of { (theta, head) ->
+ (tvs, map scaledThing theta, head) }}
+
+tcSplitDFunTy :: Type -> ([TyVar], [Type], Class, [Type])
+-- Split the type of a dictionary function
+tcSplitDFunTy ty
+ = case tcSplitQuantPredTy ty of { (tvs, theta, head) ->
+ case tcSplitDFunHead head of { (clas, tys) ->
+ (tvs, theta, clas, tys) }}
tcSplitDFunHead :: Type -> (Class, [Type])
tcSplitDFunHead = getClassPredTys
@@ -1645,8 +1678,8 @@ checkValidClsArgs :: Bool -> Class -> [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 GHC.Tc.Validity because it is
--- called from GHC.Tc.Solver, which itself is imported by GHC.Tc.Validity
+-- This function is here in GHC.Tc.Utils.TcType, rather than in GHC.Tc.Validity,
+-- because it is called from GHC.Tc.Solver, which itself is imported by GHC.Tc.Validity
checkValidClsArgs flexible_contexts cls kts
| flexible_contexts = True
| otherwise = all hasTyVarHead tys
@@ -2261,71 +2294,11 @@ Reason: the back end falls over with panic "primRepHint:VoidRep";
{-
************************************************************************
* *
- The "Paterson size" of a type
+ Visiblities
* *
************************************************************************
-}
-{-
-Note [Paterson conditions on PredTypes]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We are considering whether *class* constraints terminate
-(see Note [Paterson conditions]). Precisely, the Paterson conditions
-would have us check that "the constraint has fewer constructors and variables
-(taken together and counting repetitions) than the head.".
-
-However, we can be a bit more refined by looking at which kind of constraint
-this actually is. There are two main tricks:
-
- 1. It seems like it should be OK not to count the tuple type constructor
- for a PredType like (Show a, Eq a) :: Constraint, since we don't
- count the "implicit" tuple in the ThetaType itself.
-
- In fact, the Paterson test just checks *each component* of the top level
- ThetaType against the size bound, one at a time. By analogy, it should be
- OK to return the size of the *largest* tuple component as the size of the
- whole tuple.
-
- 2. Once we get into an implicit parameter or equality we
- can't get back to a class constraint, so it's safe
- to say "size 0". See #4200.
-
-NB: we don't want to detect PredTypes in sizeType (and then call
-sizePred on them), or we might get an infinite loop if that PredType
-is irreducible. See #5581.
--}
-
-type TypeSize = IntWithInf
-
-sizeType :: Type -> TypeSize
--- Size of a type: the number of variables and constructors
--- Ignore kinds altogether
-sizeType = go
- where
- go ty | Just exp_ty <- coreView ty = go exp_ty
- go (TyVarTy {}) = 1
- go (TyConApp tc tys)
- | isTypeFamilyTyCon tc = infinity -- Type-family applications can
- -- expand to any arbitrary size
- | otherwise = sizeTypes (filterOutInvisibleTypes tc tys) + 1
- -- Why filter out invisible args? I suppose any
- -- size ordering is sound, but why is this better?
- -- I came across this when investigating #14010.
- go (LitTy {}) = 1
- go (FunTy _ w arg res) = go w + go arg + go res + 1
- go (AppTy fun arg) = go fun + go arg
- go (ForAllTy (Bndr tv vis) ty)
- | isVisibleForAllTyFlag vis = go (tyVarKind tv) + go ty + 1
- | otherwise = go ty + 1
- go (CastTy ty _) = go ty
- go (CoercionTy {}) = 0
-
-sizeTypes :: [Type] -> TypeSize
-sizeTypes tys = sum (map sizeType tys)
-
------------------------------------------------------------------------------------
------------------------------------------------------------------------------------
------------------------
-- | For every arg a tycon can take, the returned list says True if the argument
-- is taken visibly, and False otherwise. Ends with an infinite tail of Trues to
-- allow for oversaturation.
@@ -2347,3 +2320,231 @@ isNextArgVisible ty
| otherwise = True
-- this second case might happen if, say, we have an unzonked TauTv.
-- But TauTvs can't range over types that take invisible arguments
+
+{-
+************************************************************************
+* *
+ Paterson sizes
+* *
+************************************************************************
+-}
+
+{- Note [The PatersonSize of a type]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The PatersonSize of type is something we can compare, with `ltPatersonSize`,
+to determine if the Paterson conditions are satisfied for an instance
+declaration. See Note [Paterson conditions] in GHC.Tc.Validity.
+
+There are some wrinkles
+
+(PS1) Once we get into an implicit parameter or equality we
+ can't get back to a class constraint, so it's safe
+ to say "size 0". See #4200.
+
+ We do this with isTerminatingClass
+
+Note [Invisible arguments and termination]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When checking the ​Paterson conditions for termination an instance
+declaration, we check for the number of "constructors and variables"
+in the instance head and constraints. Question: Do we look at
+
+ * All the arguments, visible or invisible?
+ * Just the visible arguments?
+
+I think both will ensure termination, provided we are consistent.
+Currently we are /not/ consistent, which is really a bug. It's
+described in #15177, which contains a number of examples.
+The suspicious bits are the calls to filterOutInvisibleTypes.
+See also #11833.
+
+Note [Stuck type families]
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+A type-family application generally has infinite size (PS_TyFam);
+see (PC3) in Note [Paterson conditions] in GHC.Tc.Validity.
+
+But a couple of built-in type families have no axioms, and can never
+expand into anything else. They are:
+
+* (TypeError "stuff"). E.g. consider
+
+ type family F a where
+ F Int = Bool
+ F Bool = Char
+ F _ = TypeError "Bad"
+
+ We don't want to complain about possible non-termination of F, in
+ GHC.Tc.Validity.checkFamInstRhs. cf indexed-types/should_fail/T13271
+
+* (Any @k).
+
+For now we treat them as being size zero, but (#22696) I think we should
+actually treat them as big (like any other ype family) because we don't
+want to abstract over them in e.g. validDerivPred.
+
+The type-family termination test, in GHC.Tc.Validity.checkFamInstRhs, already
+has a separate call to isStuckTypeFamily, so the `F` above will still be accepted.
+-}
+
+
+data PatersonSizeFailure
+ = PSF_TyFam TyCon -- Type family
+ | PSF_Size -- Too many type constructors/variables
+ | PSF_TyVar [TyVar] -- These type variables appear more often than in instance head;
+ -- no duplicates in this list
+
+--------------------------------------
+
+data PatersonSize -- See Note [Paterson conditions] in GHC.Tc.Validity
+ = PS_TyFam TyCon -- Mentions a type family; infinite size
+
+ | PS_Vanilla { ps_tvs :: [TyVar] -- Free tyvars, including repetitions;
+ , ps_size :: Int -- Number of type constructors and variables
+ }
+ -- Always after expanding synonyms
+ -- Always ignore coercions (not user written)
+ -- ToDo: ignore invisible arguments? See Note [Invisible arguments and termination]
+
+instance Outputable PatersonSize where
+ ppr (PS_TyFam tc) = text "PS_TyFam" <+> ppr tc
+ ppr (PS_Vanilla { ps_tvs = tvs, ps_size = size })
+ = text "PS_Vanilla" <> braces (sep [ text "ps_tvs =" <+> ppr tvs <> comma
+ , text "ps_size =" <+> int size ])
+
+pSizeZero, pSizeOne :: PatersonSize
+pSizeZero = PS_Vanilla { ps_tvs = [], ps_size = 0 }
+pSizeOne = PS_Vanilla { ps_tvs = [], ps_size = 1 }
+
+ltPatersonSize :: PatersonSize -- Size of constraint
+ -> PatersonSize -- Size of instance head; never PS_TyFam
+ -> Maybe PatersonSizeFailure
+-- (ps1 `ltPatersonSize` ps2) returns
+-- Nothing iff ps1 is strictly smaller than p2
+-- Just ps_fail says what went wrong
+ltPatersonSize (PS_TyFam tc) _ = Just (PSF_TyFam tc)
+ltPatersonSize (PS_Vanilla { ps_tvs = tvs1, ps_size = s1 })
+ (PS_Vanilla { ps_tvs = tvs2, ps_size = s2 })
+ | s1 >= s2 = Just PSF_Size
+ | bad_tvs@(_:_) <- noMoreTyVars tvs1 tvs2 = Just (PSF_TyVar bad_tvs)
+ | otherwise = Nothing -- OK!
+ltPatersonSize (PS_Vanilla {}) (PS_TyFam tc)
+ = pprPanic "ltPSize" (ppr tc)
+ -- Impossible because we never have a type family in an instance head
+
+noMoreTyVars :: [TyVar] -- Free vars (with repetitions) of the constraint C
+ -> [TyVar] -- Free vars (with repetitions) of the head H
+ -> [TyVar] -- TyVars that appear more often in C than H;
+ -- no repetitions in this list
+noMoreTyVars tvs head_tvs
+ = nub (tvs \\ head_tvs) -- The (\\) is list difference; e.g.
+ -- [a,b,a,a] \\ [a,a] = [b,a]
+ -- So we are counting repetitions
+
+addPSize :: PatersonSize -> PatersonSize -> PatersonSize
+addPSize ps1@(PS_TyFam {}) _ = ps1
+addPSize _ ps2@(PS_TyFam {}) = ps2
+addPSize (PS_Vanilla { ps_tvs = tvs1, ps_size = s1 })
+ (PS_Vanilla { ps_tvs = tvs2, ps_size = s2 })
+ = PS_Vanilla { ps_tvs = tvs1 ++ tvs2, ps_size = s1 + s2 }
+ -- (++) is not very performant, but the types
+ -- are user-written and never large
+
+pSizeType :: Type -> PatersonSize
+pSizeType = pSizeTypeX emptyVarSet
+
+pSizeTypes :: [Type] -> PatersonSize
+pSizeTypes = pSizeTypesX emptyVarSet pSizeZero
+
+-- Paterson size of a type, retaining repetitions, and expanding synonyms
+-- This ignores coercions, as coercions aren't user-written
+pSizeTypeX :: VarSet -> Type -> PatersonSize
+pSizeTypeX bvs ty | Just exp_ty <- coreView ty = pSizeTypeX bvs exp_ty
+pSizeTypeX bvs (TyVarTy tv)
+ | tv `elemVarSet` bvs = pSizeOne
+ | otherwise = PS_Vanilla { ps_tvs = [tv], ps_size = 1 }
+pSizeTypeX _ (LitTy {}) = pSizeOne
+pSizeTypeX bvs (TyConApp tc tys) = pSizeTyConAppX bvs tc tys
+pSizeTypeX bvs (AppTy fun arg) = pSizeTypeX bvs fun `addPSize` pSizeTypeX bvs arg
+pSizeTypeX bvs (FunTy _ w arg res) = pSizeTypeX bvs w `addPSize` pSizeTypeX bvs arg `addPSize`
+ pSizeTypeX bvs res
+pSizeTypeX bvs (ForAllTy (Bndr tv _) ty) = pSizeTypeX bvs (tyVarKind tv) `addPSize`
+ pSizeTypeX (bvs `extendVarSet` tv) ty
+pSizeTypeX bvs (CastTy ty _) = pSizeTypeX bvs ty
+pSizeTypeX _ (CoercionTy {}) = pSizeOne
+
+pSizeTypesX :: VarSet -> PatersonSize -> [Type] -> PatersonSize
+pSizeTypesX bvs sz tys = foldr (addPSize . pSizeTypeX bvs) sz tys
+
+pSizeTyConApp :: TyCon -> [Type] -> PatersonSize
+pSizeTyConApp = pSizeTyConAppX emptyVarSet
+
+pSizeTyConAppX :: VarSet -> TyCon -> [Type] -> PatersonSize
+-- Open question: do we count all args, or just the visible ones?
+-- See Note [Invisible arguments and termination]
+pSizeTyConAppX bvs tc tys
+ | isTypeFamilyTyCon tc = pSizeTyFamApp tc
+ | otherwise = pSizeTypesX bvs pSizeOne tys
+
+pSizeTyFamApp :: TyCon -> PatersonSize
+-- See Note [Stuck type families]
+pSizeTyFamApp tc
+ | isStuckTypeFamily tc = pSizeZero
+ | otherwise = PS_TyFam tc
+
+pSizeClassPred :: Class -> [Type] -> PatersonSize
+pSizeClassPred = pSizeClassPredX emptyVarSet
+
+pSizeClassPredX :: VarSet -> Class -> [Type] -> PatersonSize
+pSizeClassPredX bvs cls tys
+ | isTerminatingClass cls -- See (PS1) in Note [The PatersonSize of a type]
+ = pSizeZero
+ | otherwise
+ = pSizeTypesX bvs pSizeOne $
+ filterOutInvisibleTypes (classTyCon cls) tys
+ -- filterOutInvisibleTypes Yuk! See Note [Invisible arguments and termination]
+
+isStuckTypeFamily :: TyCon -> Bool
+-- See Note [Stuck type families]
+isStuckTypeFamily tc
+ = tc `hasKey` errorMessageTypeErrorFamKey
+ || tc `hasKey` anyTyConKey
+
+-- | When this says "True", ignore this class constraint during
+-- a termination check
+-- See (PS1) in Note [The PatersonSize of a type]
+isTerminatingClass :: Class -> Bool
+isTerminatingClass cls
+ = isIPClass cls -- Implicit parameter constraints always terminate because
+ -- there are no instances for them --- they are only solved
+ -- by "local instances" in expressions
+ || isEqPredClass cls
+ || cls `hasKey` typeableClassKey
+ -- Typeable constraints are bigger than they appear due
+ -- to kind polymorphism, but we can never get instance divergence this way
+ || cls `hasKey` coercibleTyConKey
+
+allDistinctTyVars :: TyVarSet -> [KindOrType] -> Bool
+-- (allDistinctTyVars tvs tys) returns True if tys are
+-- a) all tyvars
+-- b) all distinct
+-- c) disjoint from tvs
+allDistinctTyVars _ [] = True
+allDistinctTyVars tkvs (ty : tys)
+ = case getTyVar_maybe ty of
+ Nothing -> False
+ Just tv | tv `elemVarSet` tkvs -> False
+ | otherwise -> allDistinctTyVars (tkvs `extendVarSet` tv) tys
+
+-----------------------
+type TypeSize = IntWithInf
+
+sizeType :: Type -> TypeSize
+-- Size of a type: the number of variables and constructors
+sizeType ty = toTypeSize (pSizeType ty)
+
+sizeTypes :: [Type] -> TypeSize
+sizeTypes tys = toTypeSize (foldr (addPSize . pSizeType) pSizeZero tys)
+
+toTypeSize :: PatersonSize -> TypeSize
+toTypeSize (PS_TyFam {}) = infinity
+toTypeSize (PS_Vanilla { ps_size = size }) = mkIntWithInf size
diff --git a/compiler/GHC/Tc/Utils/Unify.hs b/compiler/GHC/Tc/Utils/Unify.hs
index 41faa2fece..eea0ed95ef 100644
--- a/compiler/GHC/Tc/Utils/Unify.hs
+++ b/compiler/GHC/Tc/Utils/Unify.hs
@@ -1477,8 +1477,8 @@ tcSkolemiseScoped ctxt expected_ty thing_inside
= do { deep_subsumption <- xoptM LangExt.DeepSubsumption
; let skolemise | deep_subsumption = deeplySkolemise
| otherwise = topSkolemise
- ; -- This (unpleasant) rec block allows us to pass skol_info to deeplySkolemise;
- -- but skol_info can't be built until we have tv_prs
+ ; -- rec {..}: see Note [Keeping SkolemInfo inside a SkolemTv]
+ -- in GHC.Tc.Utils.TcType
rec { (wrap, tv_prs, given, rho_ty) <- skolemise skol_info expected_ty
; skol_info <- mkSkolemInfo (SigSkol ctxt expected_ty tv_prs) }
@@ -1495,7 +1495,9 @@ tcTopSkolemise ctxt expected_ty thing_inside
= do { res <- thing_inside expected_ty
; return (idHsWrapper, res) }
| otherwise
- = do { rec { (wrap, tv_prs, given, rho_ty) <- topSkolemise skol_info expected_ty
+ = do { -- rec {..}: see Note [Keeping SkolemInfo inside a SkolemTv]
+ -- in GHC.Tc.Utils.TcType
+ rec { (wrap, tv_prs, given, rho_ty) <- topSkolemise skol_info expected_ty
; skol_info <- mkSkolemInfo (SigSkol ctxt expected_ty tv_prs) }
; let skol_tvs = map snd tv_prs
diff --git a/compiler/GHC/Tc/Validity.hs b/compiler/GHC/Tc/Validity.hs
index ff1c616974..6bd86a81f0 100644
--- a/compiler/GHC/Tc/Validity.hs
+++ b/compiler/GHC/Tc/Validity.hs
@@ -17,7 +17,6 @@ module GHC.Tc.Validity (
checkValidTyFamEqn, checkValidAssocTyFamDeflt, checkConsistentFamInst,
arityErr,
checkTyConTelescope,
- allDistinctTyVars
) where
import GHC.Prelude
@@ -29,12 +28,19 @@ import GHC.Data.Maybe
import GHC.Tc.Utils.Unify ( tcSubTypeAmbiguity )
import GHC.Tc.Solver ( simplifyAmbiguityCheck )
import GHC.Tc.Instance.Class ( matchGlobalInst, ClsInstResult(..), InstanceWhat(..), AssocInstInfo(..) )
-import GHC.Core.TyCo.FVs
-import GHC.Core.TyCo.Rep
-import GHC.Core.TyCo.Ppr
-import GHC.Tc.Utils.TcType hiding ( sizeType, sizeTypes )
+import GHC.Tc.Utils.TcType
+import GHC.Tc.Types.Origin
+import GHC.Tc.Types.Rank
+import GHC.Tc.Errors.Types
+import GHC.Tc.Utils.Monad
+import GHC.Tc.Utils.Env ( tcInitTidyEnv, tcInitOpenTidyEnv )
+import GHC.Tc.Instance.FunDeps
+import GHC.Tc.Instance.Family
+
import GHC.Builtin.Types
import GHC.Builtin.Names
+import GHC.Builtin.Uniques ( mkAlphaTyVarUnique )
+
import GHC.Core.Type
import GHC.Core.Unify ( tcMatchTyX_BM, BindFlag(..) )
import GHC.Core.Coercion
@@ -42,43 +48,41 @@ import GHC.Core.Coercion.Axiom
import GHC.Core.Class
import GHC.Core.TyCon
import GHC.Core.Predicate
-import GHC.Tc.Types.Origin
-import GHC.Tc.Types.Rank
-import GHC.Tc.Errors.Types
-import GHC.Types.Error
+import GHC.Core.TyCo.FVs
+import GHC.Core.TyCo.Rep
+import GHC.Core.TyCo.Ppr
+import GHC.Core.FamInstEnv ( isDominatedBy, injectiveBranches
+ , InjectivityCheckResult(..) )
--- others:
import GHC.Iface.Type ( pprIfaceType, pprIfaceTypeApp )
import GHC.CoreToIface ( toIfaceTyCon, toIfaceTcArgs, toIfaceType )
import GHC.Hs
-import GHC.Tc.Utils.Monad
-import GHC.Tc.Utils.Env ( tcInitTidyEnv, tcInitOpenTidyEnv )
-import GHC.Tc.Instance.FunDeps
-import GHC.Core.FamInstEnv
- ( isDominatedBy, injectiveBranches, InjectivityCheckResult(..) )
-import GHC.Tc.Instance.Family
+import GHC.Driver.Session
+import qualified GHC.LanguageExtensions as LangExt
+
+import GHC.Types.Error
import GHC.Types.Basic ( UnboxedTupleOrSum(..), unboxedTupleOrSumExtension )
import GHC.Types.Name
import GHC.Types.Var.Env
import GHC.Types.Var.Set
import GHC.Types.Var ( VarBndr(..), isInvisibleFunArg, mkTyVar )
+import GHC.Types.SrcLoc
+import GHC.Types.Unique.Set( isEmptyUniqSet )
+
import GHC.Utils.FV
import GHC.Utils.Error
-import GHC.Driver.Session
import GHC.Utils.Misc
-import GHC.Data.List.SetOps
-import GHC.Types.SrcLoc
import GHC.Utils.Outputable as Outputable
import GHC.Utils.Panic
-import GHC.Builtin.Uniques ( mkAlphaTyVarUnique )
-import qualified GHC.LanguageExtensions as LangExt
+
+import GHC.Data.List.SetOps
import Language.Haskell.Syntax.Basic (FieldLabelString(..))
import Control.Monad
import Data.Foldable
import Data.Function
-import Data.List ( (\\), nub )
+import Data.List ( (\\) )
import qualified Data.List.NonEmpty as NE
{-
@@ -1659,68 +1663,67 @@ The usual functional dependency checks also apply.
Note [Valid 'deriving' predicate]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-validDerivPred checks for OK 'deriving' context. See Note [Exotic
-derived instance contexts] in GHC.Tc.Deriv. However the predicate is
-here because it uses sizeTypes, fvTypes.
+validDerivPred checks for OK 'deriving' context.
+See Note [Exotic derived instance contexts] in GHC.Tc.Deriv.Infer. However the predicate is
+here because it is quite similar to checkInstTermination.
-It checks for three things
+It checks for two things:
-(VD1) No repeated variables (hasNoDups fvs)
+(VD1) The Paterson conditions; see Note [Paterson conditions]
+ Not on do we want to check for termination (of course), but it also
+ deals with a nasty corner case:
+ instance C a b => D (T a) where ...
+ Note that 'b' isn't a parameter of T. This gives rise to all sorts of
+ problems; in particular, it's hard to compare solutions for equality
+ when finding the fixpoint, and that means the inferContext loop does
+ not converge. See #5287, #21302
-(VD2) No type constructors. This is done by comparing
- sizeTypes tys == length (fvTypes tys)
- sizeTypes counts variables and constructors; fvTypes returns variables.
- So if they are the same, there must be no constructors. But there
- might be applications thus (f (g x)).
+(VD2) No type constructors; no foralls, no equalities:
+ see Note [Exotic derived instance contexts] in GHC.Tc.Deriv.Infer
- Note that tys only includes the visible arguments of the class type
+ We check the no-type-constructor bit using tyConsOfType.
+ Wrinkle: we look only at the /visible/ arguments of the class type
constructor. Including the non-visible arguments can cause the following,
perfectly valid instance to be rejected:
class Category (cat :: k -> k -> *) where ...
newtype T (c :: * -> * -> *) a b = MkT (c a b)
instance Category c => Category (T c) where ...
- since the first argument to Category is a non-visible *, which sizeTypes
- would count as a constructor! See #11833.
+ since the first argument to Category is a non-visible *, which has a
+ type constructor! See #11833.
-(VD3) Also check for a bizarre corner case, when the derived instance decl
- would look like
- instance C a b => D (T a) where ...
- Note that 'b' isn't a parameter of T. This gives rise to all sorts of
- problems; in particular, it's hard to compare solutions for equality
- when finding the fixpoint, and that means the inferContext loop does
- not converge. See #5287, #21302
Note [Equality class instances]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We can't have users writing instances for the equality classes. But we
still need to be able to write instances for them ourselves. So we allow
instances only in the defining module.
-
-}
-validDerivPred :: TyVarSet -> PredType -> Bool
+validDerivPred :: PatersonSize -> PredType -> Bool
-- See Note [Valid 'deriving' predicate]
-validDerivPred tv_set pred
- | not (tyCoVarsOfType pred `subVarSet` tv_set)
- = False -- Check (VD3)
-
- | otherwise
+validDerivPred head_size pred
= case classifyPredType pred of
+ EqPred {} -> False -- Reject equality constraints
+ ForAllPred {} -> False -- Rejects quantified predicates
+
+ ClassPred cls tys -> check_size (pSizeClassPred cls tys)
+ && isEmptyUniqSet (tyConsOfTypes visible_tys)
+ where
+ visible_tys = filterOutInvisibleTypes (classTyCon cls) tys -- (VD2)
+
+ IrredPred {} -> check_size (pSizeType pred)
+ -- Very important that we do the "too many variable occurrences"
+ -- check here, via check_size. Example (test T21302):
+ -- instance c Eq a => Eq (BoxAssoc a)
+ -- data BAD = BAD (BoxAssoc Int) deriving( Eq )
+ -- We don't want to accept an inferred predicate (c0 Eq Int)
+ -- from that `deriving(Eq)` clause, because the c0 is fresh,
+ -- so we'll think it's a "new" one, and loop in
+ -- GHC.Tc.Deriv.Infer.simplifyInstanceContexts
- ClassPred cls tys
- | isTerminatingClass cls -> True
- -- Typeable constraints are bigger than they appear due
- -- to kind polymorphism, but that's OK
-
- | otherwise -> hasNoDups visible_fvs -- Check (VD1)
- && lengthIs visible_fvs (sizeTypes visible_tys) -- Check (VD2)
- where
- visible_tys = filterOutInvisibleTypes (classTyCon cls) tys
- visible_fvs = fvTypes visible_tys
-
- IrredPred {} -> True -- Accept (f a)
- EqPred {} -> False -- Reject equality constraints
- ForAllPred {} -> False -- Rejects quantified predicates
+ where
+ check_size pred_size = isNothing (pred_size `ltPatersonSize` head_size)
+ -- Check (VD1)
{-
************************************************************************
@@ -1730,35 +1733,73 @@ validDerivPred tv_set pred
************************************************************************
-}
-{- Note [Instances and constraint synonyms]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Currently, we don't allow instances for constraint synonyms at all.
-Consider these (#13267):
- type C1 a = Show (a -> Bool)
- instance C1 Int where -- I1
- show _ = "ur"
+{- Note [Paterson conditions]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The Paterson Conditions ensure termination of instance resolution.
+Given an instance declaration
+ instance (..., C t1.. tn, ...) => D s1 .. sm
-This elicits "show is not a (visible) method of class C1", which isn't
-a great message. But it comes from the renamer, so it's hard to improve.
+we check that each constraint in the context of the instance is
+"Paterson-smaller" than the instance head. The underlying idea of
+Paterson-smaller is that
-This needs a bit more care:
- type C2 a = (Show a, Show Int)
- instance C2 Int -- I2
+ For any ground substitution S, for each constraint P in the
+ context, S(P) has fewer type constructors, counting repetitions,
+ than the head S(H)
-If we use (splitTyConApp_maybe tau) in checkValidInstance to decompose
-the instance head, we'll expand the synonym on fly, and it'll look like
- instance (%,%) (Show Int, Show Int)
-and we /really/ don't want that. So we carefully do /not/ expand
-synonyms, by matching on TyConApp directly.
+We implement this check by checking the following syntactic conditions:
-For similar reasons, we do not use tcSplitSigmaTy when decomposing the instance
-context, as the looks through type synonyms. If we looked through type
-synonyms, then it could be possible to write an instance for a type synonym
-involving a quantified constraint (see #22570). Instead, we define
-splitInstTyForValidity, a specialized version of tcSplitSigmaTy (local to
-GHC.Tc.Validity) that does not expand type synonyms.
+(PC1) No type variable has more (shallow) occurrences in P than in H.
+
+ (If not, a substitution that replaces that variable with a big type
+ would make P have many more type constructors than H. Side note: we
+ could in principle skip this test for a variable of kind Bool,
+ since there are no big ground types we can substitute for it.)
+
+(PC2) The constraint P has fewer constructors and variables (taken
+ together and counting repetitions) than the head H. This size
+ metric is computed by sizeType.
+
+ (A substitution that replaces each variable with Int demonstrates
+ the need.)
+
+(PC3) The constraint P mentions no type functions.
+
+ (A type function application can in principle expand to a type of
+ arbitrary size, and so are rejected out of hand. See #15172.)
+
+(See Section 5 of "Understanding functional dependencies via Constraint
+Handling Rules", JFP Jan 2007; and the user manual section "Instance
+termination rules".)
+
+We measure "size" with the data type PatersonSize, in GHC.Tc.Utils.TcType.
+ data PatersonSize
+ = PS_TyFam TyCon
+ | PS_Vanilla { ps_tvs :: [TyVar] -- Free tyvars, including repetitions;
+ , ps_size :: Int} -- Number of type constructors and variables
+
+* ps_tvs deals with (PC1)
+* ps_size deals with (PC2)
+* PS_TyFam deals with (PC3)
+
+Note [Tuples in checkInstTermination]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider these two ways of giving the same instance decl (#8359):
+
+ instance (Eq a, Num a) => C (T a)
+
+ type X a = (Eq a, Num a)
+ instance X a => C (T a)
+
+In the former, `checkInstTermination` will check the size of two predicates:
+(Eq a) and (Num a). In the latter, it will see only one: (X a). But we want
+to treat the latter like the former.
+
+So the `check` function in `checkInstTermination`, we simply recurse
+if we find a constraint tuple.
-}
+
checkValidInstance :: UserTypeCtxt -> LHsSigType GhcRn -> Type -> TcM ()
checkValidInstance ctxt hs_type ty = case tau of
-- See Note [Instances and constraint synonyms]
@@ -1825,33 +1866,18 @@ splitInstTyForValidity = split_context [] . drop_foralls
| isInvisibleFunArg af = split_context (pred:preds) tau
split_context preds ty = (reverse preds, ty)
-{-
-Note [Paterson conditions]
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-Termination test: the so-called "Paterson conditions" (see Section 5 of
-"Understanding functional dependencies via Constraint Handling Rules,
-JFP Jan 2007).
-
-We check that each assertion in the context satisfies:
- (1) no variable has more occurrences in the assertion than in the head, and
- (2) the assertion has fewer constructors and variables (taken together
- and counting repetitions) than the head.
-This is only needed with -fglasgow-exts, as Haskell 98 restrictions
-(which have already been checked) guarantee termination.
-
-The underlying idea is that
-
- for any ground substitution, each assertion in the
- context has fewer type constructors than the head.
--}
-
checkInstTermination :: ThetaType -> TcPredType -> TcM ()
-- See Note [Paterson conditions]
checkInstTermination theta head_pred
= check_preds emptyVarSet theta
where
- head_fvs = fvType head_pred
- head_size = sizeType head_pred
+ head_size = pSizeType head_pred
+ -- This is inconsistent and probably wrong. pSizeType does not filter out
+ -- invisible type args (making the instance head look big), whereas the use of
+ -- pSizeClassPredX below /does/ filter them out (making the tested constraints
+ -- look smaller). I'm sure there is non termination lurking here, but see #15177
+ -- for why I didn't change it. See Note [Invisible arguments and termination]
+ -- in GHC.Tc.Utils.TcType
check_preds :: VarSet -> [PredType] -> TcM ()
check_preds foralld_tvs preds = mapM_ (check foralld_tvs) preds
@@ -1860,86 +1886,84 @@ checkInstTermination theta head_pred
check foralld_tvs pred
= case classifyPredType pred of
EqPred {} -> return () -- See #4200.
- IrredPred {} -> check2 foralld_tvs pred (sizeType pred)
- ClassPred cls tys
- | isTerminatingClass cls
- -> return ()
+ IrredPred {} -> check2 (pSizeTypeX foralld_tvs pred)
- | isCTupleClass cls -- Look inside tuple predicates; #8359
+ ClassPred cls tys
+ | isCTupleClass cls -- See Note [Tuples in checkInstTermination]
-> check_preds foralld_tvs tys
| otherwise -- Other ClassPreds
- -> check2 foralld_tvs pred bogus_size
- where
- bogus_size = 1 + sizeTypes (filterOutInvisibleTypes (classTyCon cls) tys)
- -- See Note [Invisible arguments and termination]
+ -> check2 (pSizeClassPredX foralld_tvs cls tys)
ForAllPred tvs _ head_pred'
-> check (foralld_tvs `extendVarSetList` tvs) head_pred'
-- Termination of the quantified predicate itself is checked
-- when the predicates are individually checked for validity
- check2 foralld_tvs pred pred_size
- | not (null bad_tvs) = failWithTc $ mkTcRnUnknownMessage $ mkPlainError noHints $
- (noMoreMsg bad_tvs what (ppr head_pred))
- | not (isTyFamFree pred) = failWithTc $ mkTcRnUnknownMessage $ mkPlainError noHints $
- (nestedMsg what)
- | pred_size >= head_size = failWithTc $ mkTcRnUnknownMessage $ mkPlainError noHints $
- (smallerMsg what (ppr head_pred))
- | otherwise = return ()
- -- isTyFamFree: see Note [Type families in instance contexts]
- where
- what = text "constraint" <+> quotes (ppr pred)
- bad_tvs = filterOut (`elemVarSet` foralld_tvs) (fvType pred)
- \\ head_fvs
-
-smallerMsg :: SDoc -> SDoc -> SDoc
-smallerMsg what inst_head
- = vcat [ hang (text "The" <+> what)
- 2 (sep [ text "is no smaller than"
- , text "the instance head" <+> quotes inst_head ])
- , parens undecidableMsg ]
+ where
+ check2 pred_size
+ = case pred_size `ltPatersonSize` head_size of
+ Just ps_failure -> failWithTc $ mkInstSizeError ps_failure head_pred pred
+ Nothing -> return ()
-noMoreMsg :: [TcTyVar] -> SDoc -> SDoc -> SDoc
-noMoreMsg tvs what inst_head
- = vcat [ hang (text "Variable" <> plural tvs1 <+> quotes (pprWithCommas ppr tvs1)
- <+> occurs <+> text "more often")
- 2 (sep [ text "in the" <+> what
- , text "than in the instance head" <+> quotes inst_head ])
+
+mkInstSizeError :: PatersonSizeFailure -> TcPredType -> TcPredType -> TcRnMessage
+mkInstSizeError ps_failure head_pred pred
+ = mkTcRnUnknownMessage $ mkPlainError noHints $
+ vcat [ main_msg
, parens undecidableMsg ]
where
- tvs1 = nub tvs
- occurs = if isSingleton tvs1 then text "occurs"
- else text "occur"
+ pp_head = text "instance head" <+> quotes (ppr head_pred)
+ pp_pred = text "constraint" <+> quotes (ppr pred)
+
+ main_msg = case ps_failure of
+ PSF_TyFam tc -> -- See (PC3) of Note [Paterson conditions]
+ hang (text "Illegal use of type family" <+> quotes (ppr tc))
+ 2 (text "in the" <+> pp_pred)
+ PSF_TyVar tvs -> hang (occMsg tvs)
+ 2 (sep [ text "in the" <+> pp_pred
+ , text "than in the" <+> pp_head ])
+ PSF_Size -> hang (text "The" <+> pp_pred)
+ 2 (sep [ text "is no smaller than", text "the" <+> pp_head ])
+
+occMsg :: [TyVar] -> SDoc
+occMsg tvs = text "Variable" <> plural tvs <+> quotes (pprWithCommas ppr tvs)
+ <+> pp_occurs <+> text "more often"
+ where
+ pp_occurs | isSingleton tvs = text "occurs"
+ | otherwise = text "occur"
undecidableMsg :: SDoc
undecidableMsg = text "Use UndecidableInstances to permit this"
-{- Note [Type families in instance contexts]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Are these OK?
- type family F a
- instance F a => C (Maybe [a]) where ...
- instance C (F a) => C [[[a]]] where ...
-No: the type family in the instance head might blow up to an
-arbitrarily large type, depending on how 'a' is instantiated.
-So we require UndecidableInstances if we have a type family
-in the instance head. #15172.
+{- Note [Instances and constraint synonyms]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Currently, we don't allow instances for constraint synonyms at all.
+Consider these (#13267):
+ type C1 a = Show (a -> Bool)
+ instance C1 Int where -- I1
+ show _ = "ur"
-Note [Invisible arguments and termination]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When checking the ​Paterson conditions for termination an instance
-declaration, we check for the number of "constructors and variables"
-in the instance head and constraints. Question: Do we look at
+This elicits "show is not a (visible) method of class C1", which isn't
+a great message. But it comes from the renamer, so it's hard to improve.
+
+This needs a bit more care:
+ type C2 a = (Show a, Show Int)
+ instance C2 Int -- I2
- * All the arguments, visible or invisible?
- * Just the visible arguments?
+If we use (splitTyConApp_maybe tau) in checkValidInstance to decompose
+the instance head, we'll expand the synonym on fly, and it'll look like
+ instance (%,%) (Show Int, Show Int)
+and we /really/ don't want that. So we carefully do /not/ expand
+synonyms, by matching on TyConApp directly.
-I think both will ensure termination, provided we are consistent.
-Currently we are /not/ consistent, which is really a bug. It's
-described in #15177, which contains a number of examples.
-The suspicious bits are the calls to filterOutInvisibleTypes.
+For similar reasons, we do not use tcSplitSigmaTy when decomposing the instance
+context, as the looks through type synonyms. If we looked through type
+synonyms, then it could be possible to write an instance for a type synonym
+involving a quantified constraint (see #22570). Instead, we define
+splitInstTyForValidity, a specialized version of tcSplitSigmaTy (local to
+GHC.Tc.Validity) that does not expand type synonyms.
-}
@@ -2118,33 +2142,46 @@ checkValidAssocTyFamDeflt fam_tc pats =
suggestion = text "The arguments to" <+> quotes (ppr fam_tc)
<+> text "must all be distinct type variables"
--- Make sure that each type family application is
--- (1) strictly smaller than the lhs,
--- (2) mentions no type variable more often than the lhs, and
--- (3) does not contain any further type family instances.
---
checkFamInstRhs :: TyCon -> [Type] -- LHS
-> [(TyCon, [Type])] -- type family calls in RHS
-> [TcRnMessage]
+-- Ensure that the type family instance terminates. Specifically:
+-- ensure that each type family application in the RHS is
+-- (TF1) a call to a stuck family like (TypeError ...) or Any
+-- See Note [Stuck type families] in GHC.Tc.Utils.TcType
+-- or (TF2) obeys the Paterson conditions, namely:
+-- - strictly smaller than the lhs,
+-- - mentions no type variable more often than the lhs, and
+-- - does not contain any further type family applications
checkFamInstRhs lhs_tc lhs_tys famInsts
- = map (mkTcRnUnknownMessage . mkPlainError noHints) $ mapMaybe check famInsts
+ = mapMaybe check famInsts
where
- lhs_size = sizeTyConAppArgs lhs_tc lhs_tys
- inst_head = pprType (TyConApp lhs_tc lhs_tys)
- lhs_fvs = fvTypes lhs_tys
+ lhs_size = pSizeTypes lhs_tys
check (tc, tys)
- | not (all isTyFamFree tys) = Just (nestedMsg what)
- | not (null bad_tvs) = Just (noMoreMsg bad_tvs what inst_head)
- | lhs_size <= fam_app_size = Just (smallerMsg what inst_head)
- | otherwise = Nothing
- where
- what = text "type family application"
- <+> quotes (pprType (TyConApp tc tys))
- fam_app_size = sizeTyConAppArgs tc tys
- bad_tvs = fvTypes tys \\ lhs_fvs
- -- The (\\) is list difference; e.g.
- -- [a,b,a,a] \\ [a,a] = [b,a]
- -- So we are counting repetitions
+ | not (isStuckTypeFamily tc) -- (TF1)
+ , Just ps_failure <- pSizeTypes tys `ltPatersonSize` lhs_size -- (TF2)
+ = Just $ mkFamSizeError ps_failure (TyConApp lhs_tc lhs_tys) (TyConApp tc tys)
+ | otherwise
+ = Nothing
+
+mkFamSizeError :: PatersonSizeFailure -> Type -> Type -> TcRnMessage
+mkFamSizeError ps_failure lhs fam_call
+ = mkTcRnUnknownMessage $ mkPlainError noHints $
+ vcat [ main_msg
+ , parens undecidableMsg ]
+ where
+ pp_lhs = text "LHS of the family instance" <+> quotes (ppr lhs)
+ pp_call = text "type-family application" <+> quotes (ppr fam_call)
+
+ main_msg = case ps_failure of
+ PSF_TyFam tc -> -- See (PC3) of Note [Paterson conditions]
+ hang (text "Illegal nested use of type family" <+> quotes (ppr tc))
+ 2 (text "in the arguments of the" <+> pp_call)
+ PSF_TyVar tvs -> hang (occMsg tvs)
+ 2 (sep [ text "in the" <+> pp_call
+ , text "than in the" <+> pp_lhs ])
+ PSF_Size -> hang (text "The" <+> pp_call)
+ 2 (sep [ text "is no smaller than", text "the" <+> pp_lhs ])
-----------------
checkFamPatBinders :: TyCon
@@ -2249,11 +2286,6 @@ inaccessibleCoAxBranch fam_tc cur_branch
= text "Type family instance equation is overlapped:" $$
nest 2 (pprCoAxBranchUser fam_tc cur_branch)
-nestedMsg :: SDoc -> SDoc
-nestedMsg what
- = sep [ text "Illegal nested" <+> what
- , parens undecidableMsg ]
-
-------------------------
checkConsistentFamInst :: AssocInstInfo
-> TyCon -- ^ Family tycon
@@ -2812,70 +2844,3 @@ checkTyConTelescope tc
2 (vcat [ sep [ pp_inf, text "always come first"]
, sep [text "then Specified variables", pp_spec]])
-{-
-************************************************************************
-* *
-\subsection{Auxiliary functions}
-* *
-************************************************************************
--}
-
--- Free variables of a type, retaining repetitions, and expanding synonyms
--- This ignores coercions, as coercions aren't user-written
-fvType :: Type -> [TyCoVar]
-fvType ty | Just exp_ty <- coreView ty = fvType exp_ty
-fvType (TyVarTy tv) = [tv]
-fvType (TyConApp _ tys) = fvTypes tys
-fvType (LitTy {}) = []
-fvType (AppTy fun arg) = fvType fun ++ fvType arg
-fvType (FunTy _ w arg res) = fvType w ++ fvType arg ++ fvType res
-fvType (ForAllTy (Bndr tv _) ty)
- = fvType (tyVarKind tv) ++
- filter (/= tv) (fvType ty)
-fvType (CastTy ty _) = fvType ty
-fvType (CoercionTy {}) = []
-
-fvTypes :: [Type] -> [TyVar]
-fvTypes tys = concatMap fvType tys
-
-sizeType :: Type -> Int
--- Size of a type: the number of variables and constructors
-sizeType ty | Just exp_ty <- coreView ty = sizeType exp_ty
-sizeType (TyVarTy {}) = 1
-sizeType (TyConApp tc tys) = 1 + sizeTyConAppArgs tc tys
-sizeType (LitTy {}) = 1
-sizeType (AppTy fun arg) = sizeType fun + sizeType arg
-sizeType (FunTy _ w arg res) = sizeType w + sizeType arg + sizeType res + 1
-sizeType (ForAllTy _ ty) = sizeType ty
-sizeType (CastTy ty _) = sizeType ty
-sizeType (CoercionTy _) = 0
-
-sizeTypes :: [Type] -> Int
-sizeTypes = foldr ((+) . sizeType) 0
-
-sizeTyConAppArgs :: TyCon -> [Type] -> Int
-sizeTyConAppArgs _tc tys = sizeTypes tys -- (filterOutInvisibleTypes tc tys)
- -- See Note [Invisible arguments and termination]
-
--- | When this says "True", ignore this class constraint during
--- a termination check
-isTerminatingClass :: Class -> Bool
-isTerminatingClass cls
- = isIPClass cls -- Implicit parameter constraints always terminate because
- -- there are no instances for them --- they are only solved
- -- by "local instances" in expressions
- || isEqPredClass cls
- || cls `hasKey` typeableClassKey
- || cls `hasKey` coercibleTyConKey
-
-allDistinctTyVars :: TyVarSet -> [KindOrType] -> Bool
--- (allDistinctTyVars tvs tys) returns True if tys are
--- a) all tyvars
--- b) all distinct
--- c) disjoint from tvs
-allDistinctTyVars _ [] = True
-allDistinctTyVars tkvs (ty : tys)
- = case getTyVar_maybe ty of
- Nothing -> False
- Just tv | tv `elemVarSet` tkvs -> False
- | otherwise -> allDistinctTyVars (tkvs `extendVarSet` tv) tys
diff --git a/docs/users_guide/exts/instances.rst b/docs/users_guide/exts/instances.rst
index 7776a7f833..84276527a3 100644
--- a/docs/users_guide/exts/instances.rst
+++ b/docs/users_guide/exts/instances.rst
@@ -180,18 +180,10 @@ syntactically allowed. Some further various observations about this grammar:
.. _instance-rules:
.. _instance-termination:
-.. _undecidable-instances:
Instance termination rules
~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. extension:: UndecidableInstances
- :shortdesc: Enable undecidable instances.
-
- :since: 6.8.1
-
- Permit definition of instances which may lead to type-checker non-termination.
-
Regardless of :extension:`FlexibleInstances` and :extension:`FlexibleContexts`,
instance declarations must conform to some rules that ensure that
instance resolution will terminate. The restrictions can be lifted with
@@ -212,6 +204,9 @@ The rules are these:
application can in principle expand to a type of arbitrary size,
and so are rejected out of hand
+ If these three conditions hold we say that the constraint ``(C t1 ... tn)`` is
+ **Paterson-smaller** than the instance head.
+
2. The Coverage Condition. For each functional dependency,
⟨tvs⟩\ :sub:`left` ``->`` ⟨tvs⟩\ :sub:`right`, of the class, every
type variable in S(⟨tvs⟩\ :sub:`right`) must appear in
@@ -318,10 +313,99 @@ indeed the (somewhat strange) definition:
makes instance inference go into a loop, because it requires the
constraint ``(Mul a [b] b)``.
-The :extension:`UndecidableInstances` extension is also used to lift some of the
-restrictions imposed on type family instances. See
+.. _undecidable-instances:
+
+Undecidable instances and loopy superclasses
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. extension:: UndecidableInstances
+ :shortdesc: Enable undecidable instances.
+
+ :since: 6.8.1
+
+ Permit definition of instances which may lead to type-checker non-termination.
+
+The :extension:`UndecidableInstances` extension lifts the restrictions on
+on instance declarations described in :ref:`instance-termination`.
+The :extension:`UndecidableInstances` extension also lifts some of the
+restrictions imposed on type family instances; see
:ref:`type-family-decidability`.
+
+With :extension:`UndecidableInstances` it is possible to create a superclass cycle,
+which leads to the program failing to terminate. To avoid this, GHC imposes
+rules on the way in which superclass constraints are satisfied in an instance
+declaration. These rules apply even when :extension:`UndecidableInstances` is enabled.
+Consider::
+
+ class C a => D a where ...
+
+ instance Wombat [b] => D [b] where ...
+
+When typechecking this ``instance`` declaration, GHC must ensure that ``D``'s superclass,
+``(C [b])`` is satisfied. We say that ``(C [b])`` is a **Wanted superclass constraint** of the
+instance declaration.
+
+If there is an ``instance blah => C [b]``, which is often the
+case, GHC can use the instance declaration and all is well. But suppose there is no
+such instance, so GHC can only satisfy the Wanted ``(C [b])`` from the context of the instance,
+namely the Given constraint ``(Wombat [b])``. Perhaps the declaration of ``Wombat`` looks like this::
+
+ class C a => Wombat a
+
+So the Given ``(Wombat [b])`` has a superclass ``(C [b])``, and it looks as if we can satisfy the
+Wanted ``(C [b])`` constraint from this superclass of ``Wombat``. But it turns out that
+allowing this can lead to subtle looping dictionaries, and GHC prevents it.
+
+The rule is this: **a Wanted superclass constraint can only be satisfied in one of these three ways:**
+
+.. rst-class:: open
+
+1. *Directly from the context of the instance declaration*. For example, if the declaration looked like this::
+
+ instance (Wombat [b], C [b]) => D [b] where ...
+
+ we could satisfy the Wanted ``(C [b])`` from the Given ``(C [b])``.
+
+2. *Using another instance declaration*. For example, if we had::
+
+ instance C b => C [b] where ...
+
+ we can satisfy the Wanted superclass constraint ``(C [b])`` using this instance,
+ reducing it to the Wanted constraint ``(C b)`` (which still has to be solved).
+
+3. *Using the immediate superclass of a Given constraint X that is Paterson-smaller than the head of the instance declaration.*
+ The rules for Paterson-smaller are precisely those described in :ref:`instance-rules`:
+
+ - No type variable can occur more often in X than in the instance head.
+
+ - X must have fewer type constructors and variables (taken together and counting repetitions) than the instance head.
+
+ - X must mention no type functions.
+
+Rule (3) is the tricky one. Here is an example, taken from GHC's own source code::
+
+ class Ord r => UserOfRegs r a where ...
+ (i1) instance UserOfRegs r a => UserOfRegs r (Maybe a) where
+ (i2) instance (Ord r, UserOfRegs r CmmReg) => UserOfRegs r CmmExpr where
+
+For ``(i1)`` we can get the ``(Ord r)`` superclass by selection from
+``(UserOfRegs r a)``, since it (i.e. ``UserOfRegs r a``) is Paterson-smaller than the
+head of the instance declaration, namely ``(UserOfRegs r (Maybe a))``.
+
+But for ``(i2)`` that isn't the case: ``(UserOfRegs r CmmReg)`` is not Paterson-smaller
+than the head of the instance ``(UserOfRegs r CmmExpr)``, so we can't use
+the superclasses of the former. Hence we must instead add an explicit,
+and perhaps surprising, ``(Ord r)`` argument to the instance declaration.
+
+This fix, of simply adding an apparently-redundant constraint to the context
+of an instance declaration, is robust: it always fixes the problem.
+(We considered adding it automatically, but decided that it was better be explicit.)
+
+Fixing this subtle superclass cycle has a long history; if you are interested, read
+``Note [Recursive superclasses]`` and ``Note [Solving superclass constraints]``
+in ``GHC.Tc.TyCl.Instance``.
+
.. _instance-overlap:
Overlapping instances
diff --git a/testsuite/tests/deriving/should_compile/T14339.hs b/testsuite/tests/deriving/should_compile/T14339.hs
index e2521f2de0..098b6e829a 100644
--- a/testsuite/tests/deriving/should_compile/T14339.hs
+++ b/testsuite/tests/deriving/should_compile/T14339.hs
@@ -5,9 +5,6 @@ module Bug where
import GHC.TypeLits
-newtype Baz = Baz Foo
- deriving Bar
-
newtype Foo = Foo Int
class Bar a where
@@ -15,3 +12,14 @@ class Bar a where
instance (TypeError (Text "Boo")) => Bar Foo where
bar = undefined
+
+newtype Baz = Baz Foo
+ deriving Bar
+
+-- Apparently we derive
+-- instance TypeError (Text "Boo") => Bar Baz
+--
+-- Is that really what we want? It defers the type
+-- error... surely we should use standalone deriving
+-- if that is what we want?
+-- See GHC.Tc.Validity.validDerivPred and #22696. \ No newline at end of file
diff --git a/testsuite/tests/deriving/should_fail/T21302.hs b/testsuite/tests/deriving/should_fail/T21302.hs
index 16e7cf320d..2e073e6f3c 100644
--- a/testsuite/tests/deriving/should_fail/T21302.hs
+++ b/testsuite/tests/deriving/should_fail/T21302.hs
@@ -10,3 +10,9 @@ type family Assoc a
data BoxAssoc a = BoxAssoc (Assoc a)
deriving instance c Eq a => Eq (BoxAssoc a)
+
+{-
+[W] Eq (BoxAssoc Int)
+==>
+[W] c0 Eq Int
+-}
diff --git a/testsuite/tests/deriving/should_fail/T8165_fail2.stderr b/testsuite/tests/deriving/should_fail/T8165_fail2.stderr
index c0ceabf920..99e2c5fdbb 100644
--- a/testsuite/tests/deriving/should_fail/T8165_fail2.stderr
+++ b/testsuite/tests/deriving/should_fail/T8165_fail2.stderr
@@ -1,6 +1,6 @@
T8165_fail2.hs:9:12: error:
- • The type family application ‘T Loop’
- is no smaller than the instance head ‘T Loop’
+ • The type-family application ‘T Loop’
+ is no smaller than the LHS of the family instance ‘T Loop’
(Use UndecidableInstances to permit this)
• In the instance declaration for ‘C Loop’
diff --git a/testsuite/tests/impredicative/T17332.stderr b/testsuite/tests/impredicative/T17332.stderr
index 5fb876b8c5..97c35bf70a 100644
--- a/testsuite/tests/impredicative/T17332.stderr
+++ b/testsuite/tests/impredicative/T17332.stderr
@@ -1,5 +1,7 @@
T17332.hs:13:7: error: [GHC-05617]
- • Could not solve: ‘a’ arising from a use of ‘MkDict’
+ • Could not solve: ‘a’
+ arising from the head of a quantified constraint
+ arising from a use of ‘MkDict’
• In the expression: MkDict
In an equation for ‘aux’: aux = MkDict
diff --git a/testsuite/tests/indexed-types/should_fail/NotRelaxedExamples.stderr b/testsuite/tests/indexed-types/should_fail/NotRelaxedExamples.stderr
index 500be78a5f..733d90eafc 100644
--- a/testsuite/tests/indexed-types/should_fail/NotRelaxedExamples.stderr
+++ b/testsuite/tests/indexed-types/should_fail/NotRelaxedExamples.stderr
@@ -1,17 +1,18 @@
NotRelaxedExamples.hs:9:15: error:
- • Illegal nested type family application ‘F1 (F1 Char)’
+ • Illegal nested use of type family ‘F1’
+ in the arguments of the type-family application ‘F1 (F1 Char)’
(Use UndecidableInstances to permit this)
• In the type instance declaration for ‘F1’
NotRelaxedExamples.hs:10:15: error:
- • The type family application ‘F2 [x]’
- is no smaller than the instance head ‘F2 [x]’
+ • The type-family application ‘F2 [x]’
+ is no smaller than the LHS of the family instance ‘F2 [x]’
(Use UndecidableInstances to permit this)
• In the type instance declaration for ‘F2’
NotRelaxedExamples.hs:11:15: error:
- • The type family application ‘F3 [Char]’
- is no smaller than the instance head ‘F3 Bool’
+ • The type-family application ‘F3 [Char]’
+ is no smaller than the LHS of the family instance ‘F3 Bool’
(Use UndecidableInstances to permit this)
• In the type instance declaration for ‘F3’
diff --git a/testsuite/tests/indexed-types/should_fail/T10817.stderr b/testsuite/tests/indexed-types/should_fail/T10817.stderr
index af8acae33a..b6851fe0f6 100644
--- a/testsuite/tests/indexed-types/should_fail/T10817.stderr
+++ b/testsuite/tests/indexed-types/should_fail/T10817.stderr
@@ -1,7 +1,7 @@
T10817.hs:9:3: error:
- • The type family application ‘F a’
- is no smaller than the instance head ‘F a’
+ • The type-family application ‘F a’
+ is no smaller than the LHS of the family instance ‘F a’
(Use UndecidableInstances to permit this)
• In the default type instance declaration for ‘F’
In the class declaration for ‘C’
diff --git a/testsuite/tests/indexed-types/should_fail/T13271.stderr b/testsuite/tests/indexed-types/should_fail/T13271.stderr
index 4a8e7ebd20..81af4cbbab 100644
--- a/testsuite/tests/indexed-types/should_fail/T13271.stderr
+++ b/testsuite/tests/indexed-types/should_fail/T13271.stderr
@@ -13,10 +13,3 @@ T13271.hs:13:3: error: [GHC-05175]
X 2 = T2 -- Defined at T13271.hs:13:3
• In the equations for closed type family ‘X’
In the type family declaration for ‘X’
-
-T13271.hs:13:3: error:
- • The type family application ‘(TypeError ...)’
- is no smaller than the instance head ‘X 2’
- (Use UndecidableInstances to permit this)
- • In the equations for closed type family ‘X’
- In the type family declaration for ‘X’
diff --git a/testsuite/tests/indexed-types/should_fail/T15172.stderr b/testsuite/tests/indexed-types/should_fail/T15172.stderr
index 8c28c5148c..b961109055 100644
--- a/testsuite/tests/indexed-types/should_fail/T15172.stderr
+++ b/testsuite/tests/indexed-types/should_fail/T15172.stderr
@@ -1,5 +1,5 @@
T15172.hs:11:10: error:
- • Illegal nested constraint ‘F a’
+ • Illegal use of type family ‘F’ in the constraint ‘F a’
(Use UndecidableInstances to permit this)
• In the instance declaration for ‘C [[a]]’
diff --git a/testsuite/tests/indexed-types/should_fail/TyFamUndec.stderr b/testsuite/tests/indexed-types/should_fail/TyFamUndec.stderr
index 4ac7e2537c..2e111b9eff 100644
--- a/testsuite/tests/indexed-types/should_fail/TyFamUndec.stderr
+++ b/testsuite/tests/indexed-types/should_fail/TyFamUndec.stderr
@@ -1,18 +1,19 @@
TyFamUndec.hs:6:15: error:
• Variable ‘b’ occurs more often
- in the type family application ‘T (b, b)’
- than in the instance head ‘T (a, [b])’
+ in the type-family application ‘T (b, b)’
+ than in the LHS of the family instance ‘T (a, [b])’
(Use UndecidableInstances to permit this)
• In the type instance declaration for ‘T’
TyFamUndec.hs:7:15: error:
- • The type family application ‘T (a, Maybe b)’
- is no smaller than the instance head ‘T (a, Maybe b)’
+ • The type-family application ‘T (a, Maybe b)’
+ is no smaller than the LHS of the family instance ‘T (a, Maybe b)’
(Use UndecidableInstances to permit this)
• In the type instance declaration for ‘T’
TyFamUndec.hs:8:15: error:
- • Illegal nested type family application ‘T (a, T b)’
+ • Illegal nested use of type family ‘T’
+ in the arguments of the type-family application ‘T (a, T b)’
(Use UndecidableInstances to permit this)
• In the type instance declaration for ‘T’
diff --git a/testsuite/tests/quantified-constraints/T19690.hs b/testsuite/tests/quantified-constraints/T19690.hs
new file mode 100644
index 0000000000..924ad35951
--- /dev/null
+++ b/testsuite/tests/quantified-constraints/T19690.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE UndecidableInstances, UndecidableSuperClasses, ConstraintKinds, FlexibleInstances,
+ GADTs, QuantifiedConstraints, TypeApplications, ScopedTypeVariables #-}
+
+module T19690 where
+
+class c => Hold c
+instance c => Hold c
+
+data Dict c = c => Dict
+
+anythingDict :: Dict c
+anythingDict = go
+ where
+ go :: (Hold c => c) => Dict c
+ go = Dict
diff --git a/testsuite/tests/quantified-constraints/T19690.stderr b/testsuite/tests/quantified-constraints/T19690.stderr
new file mode 100644
index 0000000000..38c4dcda64
--- /dev/null
+++ b/testsuite/tests/quantified-constraints/T19690.stderr
@@ -0,0 +1,16 @@
+
+T19690.hs:12:16: error: [GHC-05617]
+ • Could not deduce ‘c’
+ arising from the head of a quantified constraint
+ arising from a use of ‘go’
+ from the context: Hold c
+ bound by a quantified context at T19690.hs:12:16-17
+ • In the expression: go
+ In an equation for ‘anythingDict’:
+ anythingDict
+ = go
+ where
+ go :: (Hold c => c) => Dict c
+ go = Dict
+ • Relevant bindings include
+ anythingDict :: Dict c (bound at T19690.hs:12:1)
diff --git a/testsuite/tests/quantified-constraints/T19921.stderr b/testsuite/tests/quantified-constraints/T19921.stderr
index 4ebc2d227f..7284fbdbf7 100644
--- a/testsuite/tests/quantified-constraints/T19921.stderr
+++ b/testsuite/tests/quantified-constraints/T19921.stderr
@@ -1,6 +1,9 @@
T19921.hs:29:8: error: [GHC-05617]
- • Could not deduce ‘r’ arising from a use of ‘Dict’
+ • Could not deduce ‘r’
+ arising from the head of a quantified constraint
+ arising from the head of a quantified constraint
+ arising from a use of ‘Dict’
from the context: (x \/ y) \/ z
bound by a quantified context at T19921.hs:29:8-11
or from: (x ⇒ r, (y \/ z) ⇒ r)
diff --git a/testsuite/tests/quantified-constraints/T21006.stderr b/testsuite/tests/quantified-constraints/T21006.stderr
index 1abacf8eb5..7eb7c88a07 100644
--- a/testsuite/tests/quantified-constraints/T21006.stderr
+++ b/testsuite/tests/quantified-constraints/T21006.stderr
@@ -1,6 +1,7 @@
T21006.hs:14:10: error: [GHC-05617]
• Could not deduce ‘c’
+ arising from the head of a quantified constraint
arising from the superclasses of an instance declaration
from the context: (Determines b, Determines c)
bound by a quantified context at T21006.hs:14:10-15
diff --git a/testsuite/tests/quantified-constraints/all.T b/testsuite/tests/quantified-constraints/all.T
index fba21ff79d..b3d0eb920f 100644
--- a/testsuite/tests/quantified-constraints/all.T
+++ b/testsuite/tests/quantified-constraints/all.T
@@ -40,3 +40,4 @@ test('T22216c', normal, compile, [''])
test('T22216d', normal, compile, [''])
test('T22216e', normal, compile, [''])
test('T22223', normal, compile, [''])
+test('T19690', normal, compile_fail, [''])
diff --git a/testsuite/tests/typecheck/should_compile/T15473.stderr b/testsuite/tests/typecheck/should_compile/T15473.stderr
index 6fdeaa115c..42aeee63c2 100644
--- a/testsuite/tests/typecheck/should_compile/T15473.stderr
+++ b/testsuite/tests/typecheck/should_compile/T15473.stderr
@@ -1,8 +1,9 @@
T15473.hs:11:3: error:
• Variable ‘a’ occurs more often
- in the type family application ‘Undefined’
- than in the instance head ‘LetInterleave xs t ts is y z’
+ in the type-family application ‘Undefined’
+ than in the LHS of the family instance ‘LetInterleave
+ xs t ts is y z’
(Use UndecidableInstances to permit this)
• In the equations for closed type family ‘LetInterleave’
In the type family declaration for ‘LetInterleave’
diff --git a/testsuite/tests/typecheck/should_compile/abstract_refinement_hole_fits.stderr b/testsuite/tests/typecheck/should_compile/abstract_refinement_hole_fits.stderr
index d34792964a..628a78aea6 100644
--- a/testsuite/tests/typecheck/should_compile/abstract_refinement_hole_fits.stderr
+++ b/testsuite/tests/typecheck/should_compile/abstract_refinement_hole_fits.stderr
@@ -41,12 +41,22 @@ abstract_refinement_hole_fits.hs:4:5: warning: [GHC-88464] [-Wtyped-holes (in -W
where flip :: forall a b c. (a -> b -> c) -> b -> a -> c
($) (_ :: [Integer] -> Integer)
where ($) :: forall a b. (a -> b) -> a -> b
+ ($!) (_ :: [Integer] -> Integer)
+ where ($!) :: forall a b. (a -> b) -> a -> b
+ id (_ :: t0 -> [Integer] -> Integer) (_ :: t0)
+ where id :: forall a. a -> a
+ head (_ :: [t0 -> [Integer] -> Integer]) (_ :: t0)
+ where head :: forall a. GHC.Stack.Types.HasCallStack => [a] -> a
+ last (_ :: [t0 -> [Integer] -> Integer]) (_ :: t0)
+ where last :: forall a. GHC.Stack.Types.HasCallStack => [a] -> a
+ fst (_ :: (t0 -> [Integer] -> Integer, b1)) (_ :: t0)
+ where fst :: forall a b. (a, b) -> a
+ snd (_ :: (a2, t0 -> [Integer] -> Integer)) (_ :: t0)
+ where snd :: forall a b. (a, b) -> b
return (_ :: Integer)
where return :: forall (m :: * -> *) a. Monad m => a -> m a
pure (_ :: Integer)
where pure :: forall (f :: * -> *) a. Applicative f => a -> f a
- ($!) (_ :: [Integer] -> Integer)
- where ($!) :: forall a b. (a -> b) -> a -> b
(>>=) (_ :: [Integer] -> a8) (_ :: a8 -> [Integer] -> Integer)
where (>>=) :: forall (m :: * -> *) a b.
Monad m =>
@@ -83,16 +93,6 @@ abstract_refinement_hole_fits.hs:4:5: warning: [GHC-88464] [-Wtyped-holes (in -W
where (<$) :: forall (f :: * -> *) a b.
Functor f =>
a -> f b -> f a
- id (_ :: t0 -> [Integer] -> Integer) (_ :: t0)
- where id :: forall a. a -> a
- head (_ :: [t0 -> [Integer] -> Integer]) (_ :: t0)
- where head :: forall a. GHC.Stack.Types.HasCallStack => [a] -> a
- last (_ :: [t0 -> [Integer] -> Integer]) (_ :: t0)
- where last :: forall a. GHC.Stack.Types.HasCallStack => [a] -> a
- fst (_ :: (t0 -> [Integer] -> Integer, b1)) (_ :: t0)
- where fst :: forall a b. (a, b) -> a
- snd (_ :: (a2, t0 -> [Integer] -> Integer)) (_ :: t0)
- where snd :: forall a b. (a, b) -> b
id (_ :: [Integer] -> Integer)
where id :: forall a. a -> a
head (_ :: [[Integer] -> Integer])
@@ -117,12 +117,12 @@ abstract_refinement_hole_fits.hs:4:5: warning: [GHC-88464] [-Wtyped-holes (in -W
where seq :: forall a b. a -> b -> b
($) (_ :: t0 -> [Integer] -> Integer) (_ :: t0)
where ($) :: forall a b. (a -> b) -> a -> b
+ ($!) (_ :: t0 -> [Integer] -> Integer) (_ :: t0)
+ where ($!) :: forall a b. (a -> b) -> a -> b
return (_ :: [Integer] -> Integer) (_ :: t0)
where return :: forall (m :: * -> *) a. Monad m => a -> m a
pure (_ :: [Integer] -> Integer) (_ :: t0)
where pure :: forall (f :: * -> *) a. Applicative f => a -> f a
- ($!) (_ :: t0 -> [Integer] -> Integer) (_ :: t0)
- where ($!) :: forall a b. (a -> b) -> a -> b
abstract_refinement_hole_fits.hs:7:5: warning: [GHC-88464] [-Wtyped-holes (in -Wdefault)]
• Found hole: _ :: Integer -> [Integer] -> Integer
@@ -158,12 +158,22 @@ abstract_refinement_hole_fits.hs:7:5: warning: [GHC-88464] [-Wtyped-holes (in -W
where flip :: forall a b c. (a -> b -> c) -> b -> a -> c
($) (_ :: Integer -> [Integer] -> Integer)
where ($) :: forall a b. (a -> b) -> a -> b
+ ($!) (_ :: Integer -> [Integer] -> Integer)
+ where ($!) :: forall a b. (a -> b) -> a -> b
+ id (_ :: t0 -> Integer -> [Integer] -> Integer) (_ :: t0)
+ where id :: forall a. a -> a
+ head (_ :: [t0 -> Integer -> [Integer] -> Integer]) (_ :: t0)
+ where head :: forall a. GHC.Stack.Types.HasCallStack => [a] -> a
+ last (_ :: [t0 -> Integer -> [Integer] -> Integer]) (_ :: t0)
+ where last :: forall a. GHC.Stack.Types.HasCallStack => [a] -> a
+ fst (_ :: (t0 -> Integer -> [Integer] -> Integer, b1)) (_ :: t0)
+ where fst :: forall a b. (a, b) -> a
+ snd (_ :: (a2, t0 -> Integer -> [Integer] -> Integer)) (_ :: t0)
+ where snd :: forall a b. (a, b) -> b
return (_ :: [Integer] -> Integer)
where return :: forall (m :: * -> *) a. Monad m => a -> m a
pure (_ :: [Integer] -> Integer)
where pure :: forall (f :: * -> *) a. Applicative f => a -> f a
- ($!) (_ :: Integer -> [Integer] -> Integer)
- where ($!) :: forall a b. (a -> b) -> a -> b
(>>=) (_ :: Integer -> a8)
(_ :: a8 -> Integer -> [Integer] -> Integer)
where (>>=) :: forall (m :: * -> *) a b.
@@ -203,16 +213,6 @@ abstract_refinement_hole_fits.hs:7:5: warning: [GHC-88464] [-Wtyped-holes (in -W
where (<$) :: forall (f :: * -> *) a b.
Functor f =>
a -> f b -> f a
- id (_ :: t0 -> Integer -> [Integer] -> Integer) (_ :: t0)
- where id :: forall a. a -> a
- head (_ :: [t0 -> Integer -> [Integer] -> Integer]) (_ :: t0)
- where head :: forall a. GHC.Stack.Types.HasCallStack => [a] -> a
- last (_ :: [t0 -> Integer -> [Integer] -> Integer]) (_ :: t0)
- where last :: forall a. GHC.Stack.Types.HasCallStack => [a] -> a
- fst (_ :: (t0 -> Integer -> [Integer] -> Integer, b1)) (_ :: t0)
- where fst :: forall a b. (a, b) -> a
- snd (_ :: (a2, t0 -> Integer -> [Integer] -> Integer)) (_ :: t0)
- where snd :: forall a b. (a, b) -> b
id (_ :: Integer -> [Integer] -> Integer)
where id :: forall a. a -> a
head (_ :: [Integer -> [Integer] -> Integer])
@@ -239,9 +239,9 @@ abstract_refinement_hole_fits.hs:7:5: warning: [GHC-88464] [-Wtyped-holes (in -W
where seq :: forall a b. a -> b -> b
($) (_ :: t0 -> Integer -> [Integer] -> Integer) (_ :: t0)
where ($) :: forall a b. (a -> b) -> a -> b
+ ($!) (_ :: t0 -> Integer -> [Integer] -> Integer) (_ :: t0)
+ where ($!) :: forall a b. (a -> b) -> a -> b
return (_ :: Integer -> [Integer] -> Integer) (_ :: t0)
where return :: forall (m :: * -> *) a. Monad m => a -> m a
pure (_ :: Integer -> [Integer] -> Integer) (_ :: t0)
where pure :: forall (f :: * -> *) a. Applicative f => a -> f a
- ($!) (_ :: t0 -> Integer -> [Integer] -> Integer) (_ :: t0)
- where ($!) :: forall a b. (a -> b) -> a -> b
diff --git a/testsuite/tests/typecheck/should_compile/constraint_hole_fits.stderr b/testsuite/tests/typecheck/should_compile/constraint_hole_fits.stderr
index 65e213a21b..44fa618172 100644
--- a/testsuite/tests/typecheck/should_compile/constraint_hole_fits.stderr
+++ b/testsuite/tests/typecheck/should_compile/constraint_hole_fits.stderr
@@ -36,12 +36,12 @@ constraint_hole_fits.hs:4:5: warning: [GHC-88464] [-Wtyped-holes (in -Wdefault)]
where const :: forall a b. a -> b -> a
($) (_ :: [a] -> a)
where ($) :: forall a b. (a -> b) -> a -> b
+ ($!) (_ :: [a] -> a)
+ where ($!) :: forall a b. (a -> b) -> a -> b
return (_ :: a)
where return :: forall (m :: * -> *) a. Monad m => a -> m a
pure (_ :: a)
where pure :: forall (f :: * -> *) a. Applicative f => a -> f a
- ($!) (_ :: [a] -> a)
- where ($!) :: forall a b. (a -> b) -> a -> b
id (_ :: [a] -> a)
where id :: forall a. a -> a
head (_ :: [[a] -> a])
diff --git a/testsuite/tests/typecheck/should_compile/refinement_hole_fits.stderr b/testsuite/tests/typecheck/should_compile/refinement_hole_fits.stderr
index adb5ed75f2..6dc4f2ba0a 100644
--- a/testsuite/tests/typecheck/should_compile/refinement_hole_fits.stderr
+++ b/testsuite/tests/typecheck/should_compile/refinement_hole_fits.stderr
@@ -70,6 +70,11 @@ refinement_hole_fits.hs:4:5: warning: [GHC-88464] [-Wtyped-holes (in -Wdefault)]
with ($) @GHC.Types.LiftedRep @[Integer] @Integer
(imported from ‘Prelude’ at refinement_hole_fits.hs:1:8-30
(and originally defined in ‘GHC.Base’))
+ ($!) (_ :: [Integer] -> Integer)
+ where ($!) :: forall a b. (a -> b) -> a -> b
+ with ($!) @GHC.Types.LiftedRep @[Integer] @Integer
+ (imported from ‘Prelude’ at refinement_hole_fits.hs:1:8-30
+ (and originally defined in ‘GHC.Base’))
return (_ :: Integer)
where return :: forall (m :: * -> *) a. Monad m => a -> m a
with return @((->) [Integer]) @Integer
@@ -80,11 +85,6 @@ refinement_hole_fits.hs:4:5: warning: [GHC-88464] [-Wtyped-holes (in -Wdefault)]
with pure @((->) [Integer]) @Integer
(imported from ‘Prelude’ at refinement_hole_fits.hs:1:8-30
(and originally defined in ‘GHC.Base’))
- ($!) (_ :: [Integer] -> Integer)
- where ($!) :: forall a b. (a -> b) -> a -> b
- with ($!) @GHC.Types.LiftedRep @[Integer] @Integer
- (imported from ‘Prelude’ at refinement_hole_fits.hs:1:8-30
- (and originally defined in ‘GHC.Base’))
j (_ :: [Integer] -> Integer)
where j :: forall a. a -> a
with j @([Integer] -> Integer)
@@ -171,6 +171,11 @@ refinement_hole_fits.hs:7:5: warning: [GHC-88464] [-Wtyped-holes (in -Wdefault)]
with ($) @GHC.Types.LiftedRep @Integer @([Integer] -> Integer)
(imported from ‘Prelude’ at refinement_hole_fits.hs:1:8-30
(and originally defined in ‘GHC.Base’))
+ ($!) (_ :: Integer -> [Integer] -> Integer)
+ where ($!) :: forall a b. (a -> b) -> a -> b
+ with ($!) @GHC.Types.LiftedRep @Integer @([Integer] -> Integer)
+ (imported from ‘Prelude’ at refinement_hole_fits.hs:1:8-30
+ (and originally defined in ‘GHC.Base’))
return (_ :: [Integer] -> Integer)
where return :: forall (m :: * -> *) a. Monad m => a -> m a
with return @((->) Integer) @([Integer] -> Integer)
@@ -181,11 +186,6 @@ refinement_hole_fits.hs:7:5: warning: [GHC-88464] [-Wtyped-holes (in -Wdefault)]
with pure @((->) Integer) @([Integer] -> Integer)
(imported from ‘Prelude’ at refinement_hole_fits.hs:1:8-30
(and originally defined in ‘GHC.Base’))
- ($!) (_ :: Integer -> [Integer] -> Integer)
- where ($!) :: forall a b. (a -> b) -> a -> b
- with ($!) @GHC.Types.LiftedRep @Integer @([Integer] -> Integer)
- (imported from ‘Prelude’ at refinement_hole_fits.hs:1:8-30
- (and originally defined in ‘GHC.Base’))
j (_ :: Integer -> [Integer] -> Integer)
where j :: forall a. a -> a
with j @(Integer -> [Integer] -> Integer)
diff --git a/testsuite/tests/typecheck/should_fail/T14884.stderr b/testsuite/tests/typecheck/should_fail/T14884.stderr
index 30e1ffbbfc..5ce38cdecb 100644
--- a/testsuite/tests/typecheck/should_fail/T14884.stderr
+++ b/testsuite/tests/typecheck/should_fail/T14884.stderr
@@ -18,6 +18,10 @@ T14884.hs:4:5: error: [GHC-88464]
with foldMap @[] @(IO ()) @Char
(imported from ‘Prelude’ at T14884.hs:1:8-13
(and originally defined in ‘Data.Foldable’))
+ id :: forall a. a -> a
+ with id @(String -> IO ())
+ (imported from ‘Prelude’ at T14884.hs:1:8-13
+ (and originally defined in ‘GHC.Base’))
($) :: forall a b. (a -> b) -> a -> b
with ($) @GHC.Types.LiftedRep @String @(IO ())
(imported from ‘Prelude’ at T14884.hs:1:8-13
@@ -26,10 +30,6 @@ T14884.hs:4:5: error: [GHC-88464]
with ($!) @GHC.Types.LiftedRep @String @(IO ())
(imported from ‘Prelude’ at T14884.hs:1:8-13
(and originally defined in ‘GHC.Base’))
- id :: forall a. a -> a
- with id @(String -> IO ())
- (imported from ‘Prelude’ at T14884.hs:1:8-13
- (and originally defined in ‘GHC.Base’))
T14884.hs:4:7: error: [GHC-39999]
• Ambiguous type variable ‘a0’ arising from a use of ‘print’
@@ -40,7 +40,7 @@ T14884.hs:4:7: error: [GHC-39999]
-- Defined in ‘Data.Either’
instance Show Ordering -- Defined in ‘GHC.Show’
...plus 26 others
- ...plus 28 instances involving out-of-scope types
+ ...plus 29 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the first argument of ‘_’, namely ‘print’
In the expression: _ print "abc"
diff --git a/testsuite/tests/typecheck/should_fail/T15552a.stderr b/testsuite/tests/typecheck/should_fail/T15552a.stderr
index f7a6094d9e..af168c8d08 100644
--- a/testsuite/tests/typecheck/should_fail/T15552a.stderr
+++ b/testsuite/tests/typecheck/should_fail/T15552a.stderr
@@ -1,21 +1,24 @@
T15552a.hs:26:9: error:
- • Illegal nested type family application ‘GetEntryOfVal
- (FirstEntryOfVal v kvs)’
+ • Illegal nested use of type family ‘FirstEntryOfVal’
+ in the arguments of the type-family application ‘GetEntryOfVal
+ (FirstEntryOfVal v kvs)’
(Use UndecidableInstances to permit this)
• In the equations for closed type family ‘FirstEntryOfVal’
In the type family declaration for ‘FirstEntryOfVal’
T15552a.hs:26:9: error:
- • Illegal nested type family application ‘EntryOfValKey
- (FirstEntryOfVal v kvs)’
+ • Illegal nested use of type family ‘FirstEntryOfVal’
+ in the arguments of the type-family application ‘EntryOfValKey
+ (FirstEntryOfVal v kvs)’
(Use UndecidableInstances to permit this)
• In the equations for closed type family ‘FirstEntryOfVal’
In the type family declaration for ‘FirstEntryOfVal’
T15552a.hs:26:9: error:
- • Illegal nested type family application ‘EntryOfValKey
- (FirstEntryOfVal v kvs)’
+ • Illegal nested use of type family ‘FirstEntryOfVal’
+ in the arguments of the type-family application ‘EntryOfValKey
+ (FirstEntryOfVal v kvs)’
(Use UndecidableInstances to permit this)
• In the equations for closed type family ‘FirstEntryOfVal’
In the type family declaration for ‘FirstEntryOfVal’
diff --git a/testsuite/tests/typecheck/should_fail/T15801.stderr b/testsuite/tests/typecheck/should_fail/T15801.stderr
index 9c7cdabeef..922fae41a7 100644
--- a/testsuite/tests/typecheck/should_fail/T15801.stderr
+++ b/testsuite/tests/typecheck/should_fail/T15801.stderr
@@ -2,5 +2,6 @@
T15801.hs:52:10: error: [GHC-18872]
• Couldn't match representation of type: UnOp op_a -> UnOp b
with that of: op_a --> b
+ arising from the head of a quantified constraint
arising from the superclasses of an instance declaration
• In the instance declaration for ‘OpRíki (Op (*))’
diff --git a/testsuite/tests/typecheck/should_fail/T20666.hs b/testsuite/tests/typecheck/should_fail/T20666.hs
new file mode 100644
index 0000000000..279c8f4b7d
--- /dev/null
+++ b/testsuite/tests/typecheck/should_fail/T20666.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE UndecidableInstances #-}
+module Bug where
+
+type family T t
+type family S s
+
+class Show (T c) => C1 c
+class Show (T (S d)) => D d
+instance (D d, c ~ S d) => C1 c
+ -- this one fails in GHC 9.2
+
+class Show (T c) => C2 c
+instance (D d, c ~ S d, c' ~ c) => C2 c'
+ -- This one succeeded because it went via lookupInInerts.
+ -- It should fail, just like the one above.
diff --git a/testsuite/tests/typecheck/should_fail/T20666.stderr b/testsuite/tests/typecheck/should_fail/T20666.stderr
new file mode 100644
index 0000000000..bc2aad5497
--- /dev/null
+++ b/testsuite/tests/typecheck/should_fail/T20666.stderr
@@ -0,0 +1,20 @@
+
+T20666.hs:13:10: error: [GHC-39999]
+ • Could not deduce ‘Show (T c)’
+ arising from the superclasses of an instance declaration
+ from the context: (D d, c ~ S d)
+ bound by the instance declaration at T20666.hs:13:10-31
+ Possible fix:
+ If the constraint looks soluble from a superclass of the instance context,
+ read 'Undecidable instances and loopy superclasses' in the user manual
+ • In the instance declaration for ‘C1 c’
+
+T20666.hs:17:10: error: [GHC-39999]
+ • Could not deduce ‘Show (T c)’
+ arising from the superclasses of an instance declaration
+ from the context: (D d, c ~ S d, c' ~ c)
+ bound by the instance declaration at T20666.hs:17:10-40
+ Possible fix:
+ If the constraint looks soluble from a superclass of the instance context,
+ read 'Undecidable instances and loopy superclasses' in the user manual
+ • In the instance declaration for ‘C2 c'’
diff --git a/testsuite/tests/typecheck/should_fail/T20666a.hs b/testsuite/tests/typecheck/should_fail/T20666a.hs
new file mode 100644
index 0000000000..b1e4d2c174
--- /dev/null
+++ b/testsuite/tests/typecheck/should_fail/T20666a.hs
@@ -0,0 +1,12 @@
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE TypeFamilies #-}
+
+module T20666a where
+
+type family F a
+
+class Eq (F a) => D a
+class Eq (F a) => C a
+
+instance D [a] => C [a]
+
diff --git a/testsuite/tests/typecheck/should_fail/T20666a.stderr b/testsuite/tests/typecheck/should_fail/T20666a.stderr
new file mode 100644
index 0000000000..4192b88807
--- /dev/null
+++ b/testsuite/tests/typecheck/should_fail/T20666a.stderr
@@ -0,0 +1,10 @@
+
+T20666a.hs:11:10: error: [GHC-39999]
+ • Could not deduce ‘Eq (F [a])’
+ arising from the superclasses of an instance declaration
+ from the context: D [a]
+ bound by the instance declaration at T20666a.hs:11:10-23
+ Possible fix:
+ If the constraint looks soluble from a superclass of the instance context,
+ read 'Undecidable instances and loopy superclasses' in the user manual
+ • In the instance declaration for ‘C [a]’
diff --git a/testsuite/tests/typecheck/should_fail/all.T b/testsuite/tests/typecheck/should_fail/all.T
index b15a50b228..61514e725b 100644
--- a/testsuite/tests/typecheck/should_fail/all.T
+++ b/testsuite/tests/typecheck/should_fail/all.T
@@ -667,3 +667,5 @@ test('T21530a', normal, compile_fail, [''])
test('T21530b', normal, compile_fail, [''])
test('T22570', normal, compile_fail, [''])
test('T22645', normal, compile_fail, [''])
+test('T20666', normal, compile_fail, [''])
+test('T20666a', normal, compile_fail, [''])
diff --git a/testsuite/tests/typecheck/should_fail/fd-loop.stderr b/testsuite/tests/typecheck/should_fail/fd-loop.stderr
index 86a70f5b76..a9320c009a 100644
--- a/testsuite/tests/typecheck/should_fail/fd-loop.stderr
+++ b/testsuite/tests/typecheck/should_fail/fd-loop.stderr
@@ -1,6 +1,6 @@
fd-loop.hs:12:10: error:
- • Variable ‘b’ occurs more often
- in the constraint ‘C a b’ than in the instance head ‘Eq (T a)’
+ • The constraint ‘C a b’
+ is no smaller than the instance head ‘Eq (T a)’
(Use UndecidableInstances to permit this)
• In the instance declaration for ‘Eq (T a)’
diff --git a/testsuite/tests/typecheck/should_fail/tcfail108.stderr b/testsuite/tests/typecheck/should_fail/tcfail108.stderr
index 4096ad36c6..2c7db0dd71 100644
--- a/testsuite/tests/typecheck/should_fail/tcfail108.stderr
+++ b/testsuite/tests/typecheck/should_fail/tcfail108.stderr
@@ -1,7 +1,6 @@
tcfail108.hs:7:10: error:
- • Variable ‘f’ occurs more often
- in the constraint ‘Eq (f (Rec f))’
- than in the instance head ‘Eq (Rec f)’
+ • The constraint ‘Eq (f (Rec f))’
+ is no smaller than the instance head ‘Eq (Rec f)’
(Use UndecidableInstances to permit this)
• In the instance declaration for ‘Eq (Rec f)’
diff --git a/testsuite/tests/typecheck/should_fail/tcfail133.hs b/testsuite/tests/typecheck/should_fail/tcfail133.hs
index 4aded61a27..a892fbca7d 100644
--- a/testsuite/tests/typecheck/should_fail/tcfail133.hs
+++ b/testsuite/tests/typecheck/should_fail/tcfail133.hs
@@ -60,11 +60,13 @@ instance Number n
=> Add (n:@Zero) One (n:@One)
instance AddDigit n One r'
=> Add (n:@One) One (r':@Zero)
-instance (Number n1, Digit d1, Number n2, Digit n2
- ,Add n1 n2 nr', AddDigit (d1:@nr') d2 r)
+instance ( Number n1, Digit d1, Number n2, Digit n2
+ , Add n1 n2 nr', AddDigit (d1:@nr') d2 r
+ , Number r) -- Added when fixing #20666
+ -- Because (AddDigit (d1:@nr') d2 r) is not
+ -- Paterson-smaller than the instance head
=> Add (n1:@d1) (n2:@d2) r
-
foo = show $ add (One:@Zero) (One:@One)
diff --git a/testsuite/tests/typecheck/should_fail/tcfail133.stderr b/testsuite/tests/typecheck/should_fail/tcfail133.stderr
index 5b2a8944e5..ff2a76fec7 100644
--- a/testsuite/tests/typecheck/should_fail/tcfail133.stderr
+++ b/testsuite/tests/typecheck/should_fail/tcfail133.stderr
@@ -2,7 +2,7 @@
tcfail133.hs:2:61: warning: [-Wdeprecated-flags (in -Wdefault)]
-XDatatypeContexts is deprecated: It was widely considered a misfeature, and has been removed from the Haskell language.
-tcfail133.hs:68:7: error: [GHC-39999]
+tcfail133.hs:70:7: error: [GHC-39999]
• Ambiguous type variable ‘a0’ arising from a use of ‘show’
prevents the constraint ‘(Show a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
@@ -11,14 +11,14 @@ tcfail133.hs:68:7: error: [GHC-39999]
instance (Number a, Digit b, Show a, Show b) => Show (a :@ b)
-- Defined at tcfail133.hs:11:54
...plus 28 others
- ...plus 12 instances involving out-of-scope types
+ ...plus 13 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the first argument of ‘($)’, namely ‘show’
In the expression: show $ add (One :@ Zero) (One :@ One)
In an equation for ‘foo’:
foo = show $ add (One :@ Zero) (One :@ One)
-tcfail133.hs:68:14: error: [GHC-39999]
+tcfail133.hs:70:14: error: [GHC-39999]
• No instance for ‘AddDigit (Zero :@ (One :@ One)) One a0’
arising from a use of ‘add’
• In the second argument of ‘($)’, namely
diff --git a/testsuite/tests/typecheck/should_fail/tcfail154.stderr b/testsuite/tests/typecheck/should_fail/tcfail154.stderr
index a4bda5998e..0fdf2e135b 100644
--- a/testsuite/tests/typecheck/should_fail/tcfail154.stderr
+++ b/testsuite/tests/typecheck/should_fail/tcfail154.stderr
@@ -1,6 +1,6 @@
tcfail154.hs:13:10: error:
- • Variable ‘a’ occurs more often
- in the constraint ‘C a a’ than in the instance head ‘Eq (T a)’
+ • The constraint ‘C a a’
+ is no smaller than the instance head ‘Eq (T a)’
(Use UndecidableInstances to permit this)
• In the instance declaration for ‘Eq (T a)’
diff --git a/testsuite/tests/typecheck/should_fail/tcfail214.stderr b/testsuite/tests/typecheck/should_fail/tcfail214.stderr
index 83fa344834..d0b153725e 100644
--- a/testsuite/tests/typecheck/should_fail/tcfail214.stderr
+++ b/testsuite/tests/typecheck/should_fail/tcfail214.stderr
@@ -1,5 +1,5 @@
tcfail214.hs:9:10: error:
- • Illegal nested constraint ‘F a’
+ • Illegal use of type family ‘F’ in the constraint ‘F a’
(Use UndecidableInstances to permit this)
• In the instance declaration for ‘C [a]’