summaryrefslogtreecommitdiff
path: root/compiler/typecheck/TcHsType.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/typecheck/TcHsType.hs')
-rw-r--r--compiler/typecheck/TcHsType.hs317
1 files changed, 157 insertions, 160 deletions
diff --git a/compiler/typecheck/TcHsType.hs b/compiler/typecheck/TcHsType.hs
index dd6357ef68..0f6f22c074 100644
--- a/compiler/typecheck/TcHsType.hs
+++ b/compiler/typecheck/TcHsType.hs
@@ -47,14 +47,12 @@ module TcHsType (
typeLevelMode, kindLevelMode,
- kindGeneralize, checkExpectedKind_pp,
+ kindGeneralizeAll, kindGeneralizeSome, kindGeneralizeNone,
+ checkExpectedKind_pp,
-- Sort-checking kinds
tcLHsKindSig, checkDataKindSig, DataSort(..),
- -- Zonking and promoting
- zonkPromoteType,
-
-- Pattern type signatures
tcHsPatSigType, tcPatSig,
@@ -83,7 +81,6 @@ import Inst ( tcInstInvisibleTyBinders, tcInstInvisibleTyBinder )
import TyCoRep( TyCoBinder(..) ) -- Used in etaExpandAlgTyCon
import Type
import TysPrim
-import Coercion
import RdrName( lookupLocalRdrOcc )
import Var
import VarSet
@@ -266,7 +263,15 @@ tc_hs_sig_type skol_info hs_sig_type ctxt_kind
; spec_tkvs <- zonkAndScopedSort spec_tkvs
; let ty1 = mkSpecForAllTys spec_tkvs ty
- ; kvs <- kindGeneralizeLocal wanted ty1
+
+ -- This bit is very much like decideMonoTyVars in TcSimplify,
+ -- but constraints are so much simpler in kinds, it is much
+ -- easier here. (In particular, we never quantify over a
+ -- constraint in a type.)
+ ; constrained <- zonkTyCoVarsAndFV (tyCoVarsOfWC wanted)
+ ; let should_gen = not . (`elemVarSet` constrained)
+
+ ; kvs <- kindGeneralizeSome should_gen ty1
; emitResidualTvConstraint skol_info Nothing (kvs ++ spec_tkvs)
tc_lvl wanted
@@ -292,7 +297,7 @@ tcTopLHsType hs_sig_type ctxt_kind
; spec_tkvs <- zonkAndScopedSort spec_tkvs
; let ty1 = mkSpecForAllTys spec_tkvs ty
- ; kvs <- kindGeneralize ty1
+ ; kvs <- kindGeneralizeAll ty1 -- "All" because it's a top-level type
; final_ty <- zonkTcTypeToType (mkInvForAllTys kvs ty1)
; traceTc "End tcTopLHsType }" (vcat [ppr hs_ty, ppr final_ty])
; return final_ty}
@@ -375,13 +380,13 @@ tcHsTypeApp wc_ty kind
-- See Note [Wildcards in visible type application]
tcNamedWildCardBinders sig_wcs $ \ _ ->
tcCheckLHsType hs_ty kind
- -- We must promote here. Ex:
- -- f :: forall a. a
- -- g = f @(forall b. Proxy b -> ()) @Int ...
- -- After when processing the @Int, we'll have to check its kind
- -- against the as-yet-unknown kind of b. This check causes an assertion
- -- failure if we don't promote.
- ; ty <- zonkPromoteType ty
+ -- We do not kind-generalize type applications: we just
+ -- instantiate with exactly what the user says.
+ -- See Note [No generalization in type application]
+ -- We still must call kindGeneralizeNone, though, according
+ -- to Note [Recipe for checking a signature]
+ ; kindGeneralizeNone ty
+ ; ty <- zonkTcType ty
; checkValidType TypeAppCtxt ty
; return ty }
tcHsTypeApp (XHsWildCardBndrs nec) _ = noExtCon nec
@@ -401,6 +406,22 @@ constraints on it. See related Note [Wildcards in visible kind
application] and Note [The wildcard story for types] in HsTypes.hs
Ugh!
+
+Note [No generalization in type application]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We do not kind-generalize type applications. Imagine
+
+ id @(Proxy Nothing)
+
+If we kind-generalized, we would get
+
+ id @(forall {k}. Proxy @(Maybe k) (Nothing @k))
+
+which is very sneakily impredicative instantiation.
+
+There is also the possibility of mentioning a wildcard
+(`id @(Proxy _)`), which definitely should not be kind-generalized.
+
-}
{-
@@ -1664,10 +1685,9 @@ Checking a user-written signature requires several steps:
1. Generate constraints.
2. Solve constraints.
- 3. Zonk.
- 4. Promote tyvars and/or kind-generalize.
- 5. Zonk.
- 6. Check validity.
+ 3. Promote tyvars and/or kind-generalize.
+ 4. Zonk.
+ 5. Check validity.
There may be some surprises in here:
@@ -1675,40 +1695,56 @@ Step 2 is necessary for two reasons: most signatures also bring
implicitly quantified variables into scope, and solving is necessary
to get these in the right order (see Note [Keeping scoped variables in
order: Implicit]). Additionally, solving is necessary in order to
-kind-generalize correctly.
+kind-generalize correctly: otherwise, we do not know which metavariables
+are left unsolved.
-In Step 4, we have to deal with the fact that metatyvars generated
-in the type may have a bumped TcLevel, because explicit foralls
-raise the TcLevel. To avoid these variables from ever being visible
-in the surrounding context, we must obey the following dictum:
+Step 3 is done by a call to candidateQTyVarsOfType, followed by a call to
+kindGeneralize{All,Some,None}. Here, we have to deal with the fact that
+metatyvars generated in the type may have a bumped TcLevel, because explicit
+foralls raise the TcLevel. To avoid these variables from ever being visible in
+the surrounding context, we must obey the following dictum:
Every metavariable in a type must either be
- (A) promoted
- (B) generalized, or
- (C) zapped to Any
-
-If a variable is generalized, then it becomes a skolem and no longer
-has a proper TcLevel. (I'm ignoring the TcLevel on a skolem here, as
-it's not really in play here.) On the other hand, if it is not
-generalized (because we're not generalizing the construct -- e.g., pattern
-sig -- or because the metavars are constrained -- see kindGeneralizeLocal)
-we need to promote to maintain (MetaTvInv) of Note [TcLevel and untouchable type variables]
-in TcType.
+ (A) generalized, or
+ (B) promoted, or See Note [Promotion in signatures]
+ (C) zapped to Any See Note [Naughty quantification candidates] in TcMType
+
+The kindGeneralize functions do not require pre-zonking; they zonk as they
+go.
-For more about (C), see Note [Naughty quantification candidates] in TcMType.
+If you are actually doing kind-generalization, you need to bump the level
+before generating constraints, as we will only generalize variables with
+a TcLevel higher than the ambient one.
-After promoting/generalizing, we need to zonk *again* because both
+After promoting/generalizing, we need to zonk again because both
promoting and generalizing fill in metavariables.
-To avoid the double-zonk, we do two things:
- 1. When we're not generalizing:
- zonkPromoteType and friends zonk and promote at the same time.
- Accordingly, the function does steps 3-5 all at once, preventing
- the need for multiple traversals.
+Note [Promotion in signatures]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+If an unsolved metavariable in a signature is not generalized
+(because we're not generalizing the construct -- e.g., pattern
+sig -- or because the metavars are constrained -- see kindGeneralizeSome)
+we need to promote to maintain (MetaTvInv) of Note [TcLevel and untouchable type variables]
+in TcType. Note that promotion is identical in effect to generalizing
+and the reinstantiating with a fresh metavariable at the current level.
+So in some sense, we generalize *all* variables, but then re-instantiate
+some of them.
+
+Here is an example of why we must promote:
+ foo (x :: forall a. a -> Proxy b) = ...
+
+In the pattern signature, `b` is unbound, and will thus be brought into
+scope. We do not know its kind: it will be assigned kappa[2]. Note that
+kappa is at TcLevel 2, because it is invented under a forall. (A priori,
+the kind kappa might depend on `a`, so kappa rightly has a higher TcLevel
+than the surrounding context.) This kappa cannot be solved for while checking
+the pattern signature (which is not kind-generalized). When we are checking
+the *body* of foo, though, we need to unify the type of x with the argument
+type of bar. At this point, the ambient TcLevel is 1, and spotting a
+matavariable with level 2 would violate the (MetaTvInv) invariant of
+Note [TcLevel and untouchable type variables]. So, instead of kind-generalizing,
+we promote the metavariable to level 1. This is all done in kindGeneralizeNone.
- 2. When we are generalizing:
- kindGeneralize does not require a zonked type -- it zonks as it
- gathers free variables. So this way effectively sidesteps step 3.
-}
tcNamedWildCardBinders :: [Name]
@@ -2228,59 +2264,75 @@ zonkAndScopedSort spec_tkvs
-- Note [Ordering of implicit variables] in RnTypes
; return (scopedSort spec_tkvs) }
-kindGeneralize :: TcType -> TcM [KindVar]
--- Quantify the free kind variables of a kind or type
--- In the latter case the type is closed, so it has no free
--- type variables. So in both cases, all the free vars are kind vars
--- Input needn't be zonked. All variables to be quantified must
--- have a TcLevel higher than the ambient TcLevel.
--- NB: You must call solveEqualities or solveLocalEqualities before
--- kind generalization
---
--- NB: this function is just a specialised version of
--- kindGeneralizeLocal emptyWC kind_or_type
---
-kindGeneralize kind_or_type
- = do { kt <- zonkTcType kind_or_type
- ; traceTc "kindGeneralise1" (ppr kt)
- ; dvs <- candidateQTyVarsOfKind kind_or_type
- ; gbl_tvs <- tcGetGlobalTyCoVars -- Already zonked
- ; traceTc "kindGeneralize" (vcat [ ppr kind_or_type
- , ppr dvs ])
- ; quantifyTyVars gbl_tvs dvs }
-
--- | This variant of 'kindGeneralize' refuses to generalize over any
--- variables free in the given WantedConstraints. Instead, it promotes
--- these variables into an outer TcLevel. All variables to be quantified must
--- have a TcLevel higher than the ambient TcLevel. See also
--- Note [Promoting unification variables] in TcSimplify
-kindGeneralizeLocal :: WantedConstraints -> TcType -> TcM [KindVar]
-kindGeneralizeLocal wanted kind_or_type
- = do {
- -- This bit is very much like decideMonoTyVars in TcSimplify,
- -- but constraints are so much simpler in kinds, it is much
- -- easier here. (In particular, we never quantify over a
- -- constraint in a type.)
- ; constrained <- zonkTyCoVarsAndFV (tyCoVarsOfWC wanted)
- ; (_, constrained) <- promoteTyVarSet constrained
-
- ; gbl_tvs <- tcGetGlobalTyCoVars -- Already zonked
- ; let mono_tvs = gbl_tvs `unionVarSet` constrained
+-- | Generalize some of the free variables in the given type.
+-- All such variables should be *kind* variables; any type variables
+-- should be explicitly quantified (with a `forall`) before now.
+-- The supplied predicate says which free variables to quantify.
+-- But in all cases,
+-- generalize only those variables whose TcLevel is strictly greater
+-- than the ambient level. This "strictly greater than" means that
+-- you likely need to push the level before creating whatever type
+-- gets passed here. Any variable whose level is greater than the
+-- ambient level but is not selected to be generalized will be
+-- promoted. (See [Promoting unification variables] in TcSimplify
+-- and Note [Recipe for checking a signature].)
+-- The resulting KindVar are the variables to
+-- quantify over, in the correct, well-scoped order. They should
+-- generally be Inferred, not Specified, but that's really up to
+-- the caller of this function.
+kindGeneralizeSome :: (TcTyVar -> Bool)
+ -> TcType -- ^ needn't be zonked
+ -> TcM [KindVar]
+kindGeneralizeSome should_gen kind_or_type
+ = do { traceTc "kindGeneralizeSome {" (ppr kind_or_type)
-- use the "Kind" variant here, as any types we see
-- here will already have all type variables quantified;
-- thus, every free variable is really a kv, never a tv.
- ; dvs <- candidateQTyVarsOfKind kind_or_type
-
- ; traceTc "kindGeneralizeLocal" $
- vcat [ text "Wanted:" <+> ppr wanted
- , text "Kind or type:" <+> ppr kind_or_type
- , text "tcvs of wanted:" <+> pprTyVars (nonDetEltsUniqSet (tyCoVarsOfWC wanted))
- , text "constrained:" <+> pprTyVars (nonDetEltsUniqSet constrained)
- , text "mono_tvs:" <+> pprTyVars (nonDetEltsUniqSet mono_tvs)
- , text "dvs:" <+> ppr dvs ]
-
- ; quantifyTyVars mono_tvs dvs }
+ ; dvs@(DV { dv_kvs = kvs, dv_tvs = tvs }) <- candidateQTyVarsOfKind kind_or_type
+
+ ; let promote_kvs = filterVarSet (not . should_gen) $ dVarSetToVarSet kvs
+ promote_tvs = filterVarSet (not . should_gen) $ dVarSetToVarSet tvs
+
+ ; (_, promoted) <- promoteTyVarSet (promote_kvs `unionVarSet` promote_tvs)
+
+ ; gbl_tvs <- tcGetGlobalTyCoVars -- already zonked
+ ; let dvs' = dvs { dv_kvs = kvs `dVarSetMinusVarSet` promote_kvs
+ , dv_tvs = tvs `dVarSetMinusVarSet` promote_tvs }
+ ; qkvs <- quantifyTyVars gbl_tvs dvs'
+
+ ; traceTc "kindGeneralizeSome }" $
+ vcat [ text "Kind or type:" <+> ppr kind_or_type
+ , text "dvs:" <+> ppr dvs
+ , text "dvs':" <+> ppr dvs'
+ , text "promote_kvs:" <+> pprTyVars (nonDetEltsUniqSet promote_kvs)
+ , text "promote_tvs:" <+> pprTyVars (nonDetEltsUniqSet promote_tvs)
+ , text "promoted:" <+> pprTyVars (nonDetEltsUniqSet promoted)
+ , text "gbl_tvs:" <+> pprTyVars (nonDetEltsUniqSet gbl_tvs)
+ , text "qkvs:" <+> pprTyVars qkvs ]
+
+ ; return qkvs }
+
+-- | Specialized version of 'kindGeneralizeSome', but where all variables
+-- can be generalized. Use this variant when you can be sure that no more
+-- constraints on the type's metavariables will arise or be solved.
+kindGeneralizeAll :: TcType -- needn't be zonked
+ -> TcM [KindVar]
+kindGeneralizeAll ty = do { traceTc "kindGeneralizeAll" empty
+ ; kindGeneralizeSome (const True) ty }
+
+-- | Specialized version of 'kindGeneralizeSome', but where no variables
+-- can be generalized. Use this variant when it is unknowable whether metavariables
+-- might later be constrained.
+-- See Note [Recipe for checking a signature] for why and where this
+-- function is needed.
+kindGeneralizeNone :: TcType -- needn't be zonked
+ -> TcM ()
+kindGeneralizeNone ty
+ = do { traceTc "kindGeneralizeNone" empty
+ ; kvs <- kindGeneralizeSome (const False) ty
+ ; MASSERT( null kvs )
+ }
{- Note [Levels and generalisation]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2598,6 +2650,12 @@ tcHsPartialSigType ctxt sig_ty
; return (wcs, wcx, theta, tau) }
+ -- No kind-generalization here:
+ ; kindGeneralizeNone (mkSpecForAllTys implicit_tvs $
+ mkSpecForAllTys explicit_tvs $
+ mkPhiTy theta $
+ tau)
+
-- Spit out the wildcards (including the extra-constraints one)
-- as "hole" constraints, so that they'll be reported if necessary
-- See Note [Extra-constraint holes in partial type signatures]
@@ -2741,7 +2799,9 @@ tcHsPatSigType ctxt sig_ty
-- Ex: f (x :: forall a. Proxy a -> ()) = ... x ...
-- When we instantiate x, we have to compare the kind of the argument
-- to a's kind, which will be a metavariable.
- ; sig_ty <- zonkPromoteType sig_ty
+ -- kindGeneralizeNone does this:
+ ; kindGeneralizeNone sig_ty
+ ; sig_ty <- zonkTcType sig_ty
; checkValidType ctxt sig_ty
; traceTc "tcHsPatSigType" (ppr sig_tkv_prs)
@@ -2877,70 +2937,6 @@ unifyKinds rn_tys act_kinds
{-
************************************************************************
* *
- Promotion
-* *
-************************************************************************
--}
-
--- | Whenever a type is about to be added to the environment, it's necessary
--- to make sure that any free meta-tyvars in the type are promoted to the
--- current TcLevel. (They might be at a higher level due to the level-bumping
--- in tcExplicitTKBndrs, for example.) This function both zonks *and*
--- promotes. Why at the same time? See Note [Recipe for checking a signature]
-zonkPromoteType :: TcType -> TcM TcType
-zonkPromoteType = mapType zonkPromoteMapper ()
-
--- cf. TcMType.zonkTcTypeMapper
-zonkPromoteMapper :: TyCoMapper () TcM
-zonkPromoteMapper = TyCoMapper { tcm_tyvar = const zonkPromoteTcTyVar
- , tcm_covar = const covar
- , tcm_hole = const hole
- , tcm_tycobinder = const tybinder
- , tcm_tycon = return }
- where
- covar cv
- = mkCoVarCo <$> zonkPromoteTyCoVarKind cv
-
- hole :: CoercionHole -> TcM Coercion
- hole h
- = do { contents <- unpackCoercionHole_maybe h
- ; case contents of
- Just co -> do { co <- zonkPromoteCoercion co
- ; checkCoercionHole cv co }
- Nothing -> do { cv' <- zonkPromoteTyCoVarKind cv
- ; return $ mkHoleCo (setCoHoleCoVar h cv') } }
- where
- cv = coHoleCoVar h
-
- tybinder :: TyVar -> ArgFlag -> TcM ((), TyVar)
- tybinder tv _flag = ((), ) <$> zonkPromoteTyCoVarKind tv
-
-zonkPromoteTcTyVar :: TyCoVar -> TcM TcType
-zonkPromoteTcTyVar tv
- | isMetaTyVar tv
- = do { let ref = metaTyVarRef tv
- ; contents <- readTcRef ref
- ; case contents of
- Flexi -> do { (_, promoted_tv) <- promoteTyVar tv
- ; mkTyVarTy <$> zonkPromoteTyCoVarKind promoted_tv }
- Indirect ty -> zonkPromoteType ty }
-
- | isTcTyVar tv && isSkolemTyVar tv -- NB: isSkolemTyVar says "True" to pure TyVars
- = do { tc_lvl <- getTcLevel
- ; mkTyVarTy <$> zonkPromoteTyCoVarKind (promoteSkolem tc_lvl tv) }
-
- | otherwise
- = mkTyVarTy <$> zonkPromoteTyCoVarKind tv
-
-zonkPromoteTyCoVarKind :: TyCoVar -> TcM TyCoVar
-zonkPromoteTyCoVarKind = updateTyVarKindM zonkPromoteType
-
-zonkPromoteCoercion :: Coercion -> TcM Coercion
-zonkPromoteCoercion = mapCoercion zonkPromoteMapper ()
-
-{-
-************************************************************************
-* *
Sort checking kinds
* *
************************************************************************
@@ -2956,8 +2952,9 @@ tcLHsKindSig ctxt hs_kind
= do { kind <- solveLocalEqualities "tcLHsKindSig" $
tc_lhs_kind kindLevelMode hs_kind
; traceTc "tcLHsKindSig" (ppr hs_kind $$ ppr kind)
- -- No generalization, so we must promote
- ; kind <- zonkPromoteType kind
+ -- No generalization:
+ ; kindGeneralizeNone kind
+ ; kind <- zonkTcType kind
-- This zonk is very important in the case of higher rank kinds
-- E.g. #13879 f :: forall (p :: forall z (y::z). <blah>).
-- <more blah>