diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2017-07-26 08:51:47 +0100 |
---|---|---|
committer | Simon Peyton Jones <simonpj@microsoft.com> | 2017-07-26 12:33:42 +0100 |
commit | 75bf11c037d9e82f95ac9779bfd2b1432835bd76 (patch) | |
tree | 896e4585202593c1721180ee8f47ae3fb75a0500 /compiler | |
parent | 746ab0b4a2f97d9f2a97fc28431e5bdfbc10b8cf (diff) | |
download | haskell-75bf11c037d9e82f95ac9779bfd2b1432835bd76.tar.gz |
Fix binder visiblity for default methods
Trac #13998 showed that default methods were getting bogus tyvar
binder visiblity info; and that it matters in the code genreated
by the default-method fill-in mechanism
* The actual fix: in TcTyDecls.mkDefaultMethodType, make TyVarBinders
with the right visibility info by getting TyConBinders from the
class TyCon. (Previously we made up visiblity info, but that
caused #13998.)
* Define TyCon.tyConTyVarBinders :: [TyConBinder] -> [TyVarBinder]
which can build correct forall binders for
a) default methods (Trac #13998)
b) data constructors
This was originally BuildTyCl.mkDataConUnivTyVarBinders
* Move mkTyVarBinder, mkTyVarBinders from Type to Var
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/basicTypes/Var.hs | 11 | ||||
-rw-r--r-- | compiler/iface/BuildTyCl.hs | 70 | ||||
-rw-r--r-- | compiler/iface/TcIface.hs | 2 | ||||
-rw-r--r-- | compiler/typecheck/TcPatSyn.hs | 3 | ||||
-rw-r--r-- | compiler/typecheck/TcTyClsDecls.hs | 2 | ||||
-rw-r--r-- | compiler/typecheck/TcTyDecls.hs | 14 | ||||
-rw-r--r-- | compiler/typecheck/TcType.hs | 2 | ||||
-rw-r--r-- | compiler/types/Class.hs | 4 | ||||
-rw-r--r-- | compiler/types/TyCoRep.hs | 54 | ||||
-rw-r--r-- | compiler/types/TyCon.hs | 72 | ||||
-rw-r--r-- | compiler/types/Type.hs | 8 |
11 files changed, 133 insertions, 109 deletions
diff --git a/compiler/basicTypes/Var.hs b/compiler/basicTypes/Var.hs index 87c4fe2240..58e8d525d0 100644 --- a/compiler/basicTypes/Var.hs +++ b/compiler/basicTypes/Var.hs @@ -64,6 +64,7 @@ module Var ( TyVarBndr(..), ArgFlag(..), TyVarBinder, binderVar, binderVars, binderArgFlag, binderKind, isVisibleArgFlag, isInvisibleArgFlag, sameVis, + mkTyVarBinder, mkTyVarBinders, -- ** Constructing TyVar's mkTyVar, mkTcTyVar, @@ -374,7 +375,7 @@ updateVarTypeM f id = do { ty' <- f (varType id) -- Is something required to appear in source Haskell ('Required'), -- permitted by request ('Specified') (visible type application), or -- prohibited entirely from appearing in source Haskell ('Inferred')? --- See Note [TyBinders and ArgFlags] in TyCoRep +-- See Note [TyVarBndrs, TyVarBinders, TyConBinders, and visibility] in TyCoRep data ArgFlag = Required | Specified | Inferred deriving (Eq, Data) @@ -429,6 +430,14 @@ binderArgFlag (TvBndr _ argf) = argf binderKind :: TyVarBndr TyVar argf -> Kind binderKind (TvBndr tv _) = tyVarKind tv +-- | Make a named binder +mkTyVarBinder :: ArgFlag -> Var -> TyVarBinder +mkTyVarBinder vis var = TvBndr var vis + +-- | Make many named binders +mkTyVarBinders :: ArgFlag -> [TyVar] -> [TyVarBinder] +mkTyVarBinders vis = map (mkTyVarBinder vis) + {- ************************************************************************ * * diff --git a/compiler/iface/BuildTyCl.hs b/compiler/iface/BuildTyCl.hs index 76b7793859..a5b724994c 100644 --- a/compiler/iface/BuildTyCl.hs +++ b/compiler/iface/BuildTyCl.hs @@ -6,7 +6,7 @@ {-# LANGUAGE CPP #-} module BuildTyCl ( - buildDataCon, mkDataConUnivTyVarBinders, + buildDataCon, buildPatSyn, TcMethInfo, buildClass, mkNewTyConRhs, mkDataTyConRhs, @@ -119,7 +119,6 @@ buildDataCon :: FamInstEnvs -- a) makes the worker Id -- b) makes the wrapper Id if necessary, including -- allocating its unique (hence monadic) --- c) Sorts out the TyVarBinders. See mkDataConUnivTyBinders buildDataCon fam_envs src_name declared_infix prom_info src_bangs impl_bangs field_lbls univ_tvs ex_tvs eq_spec ctxt arg_tys res_ty rep_tycon = do { wrap_name <- newImplicitBinder src_name mkDataConWrapperOcc @@ -165,69 +164,6 @@ mkDataConStupidTheta tycon arg_tys univ_tvs tyCoVarsOfType pred `intersectVarSet` arg_tyvars -mkDataConUnivTyVarBinders :: [TyConBinder] -- From the TyCon - -> [TyVarBinder] -- For the DataCon --- See Note [Building the TyBinders for a DataCon] -mkDataConUnivTyVarBinders tc_bndrs - = map mk_binder tc_bndrs - where - mk_binder (TvBndr tv tc_vis) = mkTyVarBinder vis tv - where - vis = case tc_vis of - AnonTCB -> Specified - NamedTCB Required -> Specified - NamedTCB vis -> vis - -{- Note [Building the TyBinders for a DataCon] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A DataCon needs to keep track of the visibility of its universals and -existentials, so that visible type application can work properly. This -is done by storing the universal and existential TyVarBinders. -See Note [TyVarBinders in DataCons] in DataCon. - -During construction of a DataCon, we often start from the TyBinders of -the parent TyCon. For example - data Maybe a = Nothing | Just a -The DataCons start from the TyBinders of the parent TyCon. - -But the ultimate TyBinders for the DataCon are *different* than those -of the DataCon. Here is an example: - - data App a b = MkApp (a b) -- App :: forall {k}. (k->*) -> k -> * - -The TyCon has - - tyConTyVars = [ k:*, a:k->*, b:k] - tyConTyBinders = [ Named (TvBndr (k :: *) Inferred), Anon (k->*), Anon k ] - -The TyBinders for App line up with App's kind, given above. - -But the DataCon MkApp has the type - MkApp :: forall {k} (a:k->*) (b:k). a b -> App k a b - -That is, its TyBinders should be - - dataConUnivTyVarBinders = [ TvBndr (k:*) Inferred - , TvBndr (a:k->*) Specified - , TvBndr (b:k) Specified ] - -So we want to take the TyCon's TyBinders and the TyCon's TyVars and -merge them, pulling - - variable names from the TyVars - - visibilities from the TyBinders - - but changing Anon/Required to Specified - -The last part about Required->Specified comes from this: - data T k (a:k) b = MkT (a b) -Here k is Required in T's kind, but we don't have Required binders in -the TyBinders for a term (see Note [No Required TyBinder in terms] -in TyCoRep), so we change it to Specified when making MkT's TyBinders - -This merging operation is done by mkDataConUnivTyBinders. In contrast, -the TyBinders passed to mkDataCon are the final TyBinders stored in the -DataCon (mkDataCon does no further work). --} - ------------------------------------------------------ buildPatSyn :: Name -> Bool -> (Id,Bool) -> Maybe (Id, Bool) @@ -310,7 +246,7 @@ buildClass tycon_name binders roles fds Nothing do { traceIf (text "buildClass") ; tc_rep_name <- newTyConRepName tycon_name - ; let univ_bndrs = mkDataConUnivTyVarBinders binders + ; let univ_bndrs = tyConTyVarBinders binders univ_tvs = binderVars univ_bndrs tycon = mkClassTyCon tycon_name binders roles AbstractTyCon rec_clas tc_rep_name @@ -359,7 +295,7 @@ buildClass tycon_name binders roles fds op_names = [op | (op,_,_) <- sig_stuff] arg_tys = sc_theta ++ op_tys rec_tycon = classTyCon rec_clas - univ_bndrs = mkDataConUnivTyVarBinders binders + univ_bndrs = tyConTyVarBinders binders univ_tvs = binderVars univ_bndrs ; rep_nm <- newTyConRepName datacon_name diff --git a/compiler/iface/TcIface.hs b/compiler/iface/TcIface.hs index 1477f462fc..418994d752 100644 --- a/compiler/iface/TcIface.hs +++ b/compiler/iface/TcIface.hs @@ -893,7 +893,7 @@ tcIfaceDataCons tycon_name tycon tc_tybinders if_cons ; mkNewTyConRhs tycon_name tycon data_con } where univ_tv_bndrs :: [TyVarBinder] - univ_tv_bndrs = mkDataConUnivTyVarBinders tc_tybinders + univ_tv_bndrs = tyConTyVarBinders tc_tybinders tc_con_decl (IfCon { ifConInfix = is_infix, ifConExTvs = ex_bndrs, diff --git a/compiler/typecheck/TcPatSyn.hs b/compiler/typecheck/TcPatSyn.hs index 8f99a23b08..36b63842e3 100644 --- a/compiler/typecheck/TcPatSyn.hs +++ b/compiler/typecheck/TcPatSyn.hs @@ -15,8 +15,7 @@ module TcPatSyn ( tcInferPatSynDecl, tcCheckPatSynDecl import HsSyn import TcPat -import Type( mkTyVarBinders, mkEmptyTCvSubst - , tidyTyVarBinders, tidyTypes, tidyType ) +import Type( mkEmptyTCvSubst, tidyTyVarBinders, tidyTypes, tidyType ) import TcRnMonad import TcSigs( emptyPragEnv, completeSigFromId ) import TcEnv diff --git a/compiler/typecheck/TcTyClsDecls.hs b/compiler/typecheck/TcTyClsDecls.hs index 4e7c99cde8..5acf207dc6 100644 --- a/compiler/typecheck/TcTyClsDecls.hs +++ b/compiler/typecheck/TcTyClsDecls.hs @@ -1564,7 +1564,7 @@ tcConDecl rep_tycon tmpl_bndrs res_tmpl ; buildDataCon fam_envs name is_infix rep_nm stricts Nothing field_lbls - (mkDataConUnivTyVarBinders tmpl_bndrs) + (tyConTyVarBinders tmpl_bndrs) ex_tvs [{- no eq_preds -}] ctxt arg_tys res_tmpl rep_tycon diff --git a/compiler/typecheck/TcTyDecls.hs b/compiler/typecheck/TcTyDecls.hs index 68e15fbd48..41482cca8e 100644 --- a/compiler/typecheck/TcTyDecls.hs +++ b/compiler/typecheck/TcTyDecls.hs @@ -771,10 +771,18 @@ mkDefaultMethodIds tycons mkDefaultMethodType :: Class -> Id -> DefMethSpec Type -> Type -- Returns the top-level type of the default method mkDefaultMethodType _ sel_id VanillaDM = idType sel_id -mkDefaultMethodType cls _ (GenericDM dm_ty) = mkSpecSigmaTy cls_tvs [pred] dm_ty +mkDefaultMethodType cls _ (GenericDM dm_ty) = mkSigmaTy tv_bndrs [pred] dm_ty where - cls_tvs = classTyVars cls - pred = mkClassPred cls (mkTyVarTys cls_tvs) + pred = mkClassPred cls (mkTyVarTys (binderVars cls_bndrs)) + cls_bndrs = tyConBinders (classTyCon cls) + tv_bndrs = tyConTyVarBinders cls_bndrs + -- NB: the Class doesn't have TyConBinders; we reach into its + -- TyCon to get those. We /do/ need the TyConBinders because + -- we need the correct visiblity: these default methods are + -- used in code generated by the the fill-in for missing + -- methods in instances (TcInstDcls.mkDefMethBind), and + -- then typechecked. So we need the right visibilty info + -- (Trac #13998) {- ************************************************************************ diff --git a/compiler/typecheck/TcType.hs b/compiler/typecheck/TcType.hs index e12b70b6d1..00bcea263c 100644 --- a/compiler/typecheck/TcType.hs +++ b/compiler/typecheck/TcType.hs @@ -1728,7 +1728,7 @@ tc_eq_type view_fun orig_ty1 orig_ty2 = go True orig_env orig_ty1 orig_ty2 -- be oversaturated where bndrs = tyConBinders tc - viss = map (isVisibleArgFlag . tyConBinderArgFlag) bndrs + viss = map isVisibleTyConBinder bndrs tc_vis False _ = repeat False -- if we're not in a visible context, our args -- aren't either diff --git a/compiler/types/Class.hs b/compiler/types/Class.hs index ae1047ebde..b981a4998e 100644 --- a/compiler/types/Class.hs +++ b/compiler/types/Class.hs @@ -60,6 +60,10 @@ data Class classTyVars :: [TyVar], -- The class kind and type variables; -- identical to those of the TyCon + -- If you want visiblity info, look at the classTyCon + -- This field is redundant because it's duplicated in the + -- classTyCon, but classTyVars is used quite often, so maybe + -- it's a bit faster to cache it here classFunDeps :: [FunDep TyVar], -- The functional dependencies diff --git a/compiler/types/TyCoRep.hs b/compiler/types/TyCoRep.hs index 5ac63e5b04..f5d33748e7 100644 --- a/compiler/types/TyCoRep.hs +++ b/compiler/types/TyCoRep.hs @@ -457,28 +457,38 @@ words, if `x` is either a function or a polytype, `x arg` makes sense (for an appropriate `arg`). -Note [TyBinders and ArgFlags] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A ForAllTy contains a TyVarBinder. Each TyVarBinder is equipped -with a ArgFlag, which says whether or not arguments for this -binder should be visible (explicit) in source Haskell. - ------------------------------------------------------------------------ - Occurrences look like this - TyBinder GHC displays type as in Haskell souce code ------------------------------------------------------------------------ -In the type of a term - Anon: f :: type -> type Arg required: f x - Named Inferred: f :: forall {a}. type Arg not allowed: f - Named Specified: f :: forall a. type Arg optional: f or f @Int - Named Required: Illegal: See Note [No Required TyBinder in terms] - -In the kind of a type - Anon: T :: kind -> kind Required: T * - Named Inferred: T :: forall {k}. kind Arg not allowed: T - Named Specified: T :: forall k. kind Arg not allowed[1]: T - Named Required: T :: forall k -> kind Required: T * ------------------------------------------------------------------------- +Note [TyVarBndrs, TyVarBinders, TyConBinders, and visiblity] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* A ForAllTy (used for both types and kinds) contains a TyVarBinder. + Each TyVarBinder + TvBndr a tvis + is equipped with tvis::ArgFlag, which says whether or not arguments + for this binder should be visible (explicit) in source Haskell. + +* A TyCon contains a list of TyConBinders. Each TyConBinder + TvBndr a cvis + is equipped with cvis::TyConBndrVis, which says whether or not type + and kind arguments for this TyCon should be visible (explicit) in + source Haskell. + +This table summarises the visiblity rules: +--------------------------------------------------------------------------------------- +| Occurrences look like this +| GHC displays type as in Haskell souce code +|----------------------------------------------------------------------- +| TvBndr a tvis :: TyVarBinder, in the binder of ForAllTy for a term +| tvis :: ArgFlag +| tvis = Inferred: f :: forall {a}. type Arg not allowed: f +| tvis = Specified: f :: forall a. type Arg optional: f or f @Int +| tvis = Required: Illegal: See Note [No Required TyBinder in terms] +| +| TvBndr k cvis :: TyConBinder, in the TyConBinders of a TyCon +| cvis :: TyConBndrVis +| cvis = AnonTCB: T :: kind -> kind Required: T * +| cvis = NamedTCB Inferred: T :: forall {k}. kind Arg not allowed: T +| cvis = NamedTCB Specified: T :: forall k. kind Arg not allowed[1]: T +| cvis = NamedTCB Required: T :: forall k -> kind Required: T * +--------------------------------------------------------------------------------------- [1] In types, in the Specified case, it would make sense to allow optional kind applications, thus (T @*), but we have not diff --git a/compiler/types/TyCon.hs b/compiler/types/TyCon.hs index 1be318d96a..d717ba66d3 100644 --- a/compiler/types/TyCon.hs +++ b/compiler/types/TyCon.hs @@ -94,7 +94,7 @@ module TyCon( newTyConDataCon_maybe, algTcFields, tyConRuntimeRepInfo, - tyConBinders, tyConResKind, + tyConBinders, tyConResKind, tyConTyVarBinders, tcTyConScopedTyVars, -- ** Manipulating TyCons @@ -428,6 +428,72 @@ mkTyConKind bndrs res_kind = foldr mk res_kind bndrs mk (TvBndr tv AnonTCB) k = mkFunKind (tyVarKind tv) k mk (TvBndr tv (NamedTCB vis)) k = mkForAllKind tv vis k +tyConTyVarBinders :: [TyConBinder] -- From the TyCon + -> [TyVarBinder] -- Suitable for the foralls of a term function +-- See Note [Building TyVarBinders from TyConBinders] +tyConTyVarBinders tc_bndrs + = map mk_binder tc_bndrs + where + mk_binder (TvBndr tv tc_vis) = mkTyVarBinder vis tv + where + vis = case tc_vis of + AnonTCB -> Specified + NamedTCB Required -> Specified + NamedTCB vis -> vis + +{- Note [Building TyVarBinders from TyConBinders] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +We sometimes need to build the quantified type of a value from +the TyConBinders of a type or class. For that we need not +TyConBinders but TyVarBinders (used in forall-type) E.g: + + * From data T a = MkT (Maybe a) + we are going to make a data constructor with type + MkT :: forall a. Maybe a -> T a + See the TyVarBinders passed to buildDataCon + + * From class C a where { op :: a -> Maybe a } + we are going to make a default method + $dmop :: forall a. C a => a -> Maybe a + See the TyVarBindres passed to mkSigmaTy in mkDefaultMethodType + +Both of these are user-callable. (NB: default methods are not callable +directly by the user but rather via the code generated by 'deriving', +which uses visible type application; see mkDefMethBind.) + +Since they are user-callable we must get their type-argument visibility +information right; and that info is in the TyConBinders. +Here is an example: + + data App a b = MkApp (a b) -- App :: forall {k}. (k->*) -> k -> * + +The TyCon has + + tyConTyBinders = [ Named (TvBndr (k :: *) Inferred), Anon (k->*), Anon k ] + +The TyConBinders for App line up with App's kind, given above. + +But the DataCon MkApp has the type + MkApp :: forall {k} (a:k->*) (b:k). a b -> App k a b + +That is, its TyVarBinders should be + + dataConUnivTyVarBinders = [ TvBndr (k:*) Inferred + , TvBndr (a:k->*) Specified + , TvBndr (b:k) Specified ] + +So tyConTyVarBinders conversts TyCon's TyConBinders into TyVarBinders: + - variable names from the TyConBinders + - but changing Anon/Required to Specified + +The last part about Required->Specified comes from this: + data T k (a:k) b = MkT (a b) +Here k is Required in T's kind, but we don't have Required binders in +the TyBinders for a term (see Note [No Required TyBinder in terms] +in TyCoRep), so we change it to Specified when making MkT's TyBinders +-} + + {- Note [The binders/kind/arity fields of a TyCon] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ All TyCons have this group of fields @@ -451,8 +517,8 @@ They fit together like so: Note that that are three binders here, including the kind variable k. - See Note [TyBinders and ArgFlags] in TyCoRep for what - the visibility flag means. +- See Note [TyVarBndrs, TyVarBinders, TyConBinders, and visibility] in TyCoRep + for what the visibility flag means. * Each TyConBinder tyConBinders has a TyVar, and that TyVar may scope over some other part of the TyCon's definition. Eg diff --git a/compiler/types/Type.hs b/compiler/types/Type.hs index 8621e6cd52..0764d144b7 100644 --- a/compiler/types/Type.hs +++ b/compiler/types/Type.hs @@ -1486,14 +1486,6 @@ isTauTy (CoercionTy _) = False -- Not sure about this %************************************************************************ -} --- | Make a named binder -mkTyVarBinder :: ArgFlag -> Var -> TyVarBinder -mkTyVarBinder vis var = TvBndr var vis - --- | Make many named binders -mkTyVarBinders :: ArgFlag -> [TyVar] -> [TyVarBinder] -mkTyVarBinders vis = map (mkTyVarBinder vis) - -- | Make an anonymous binder mkAnonBinder :: Type -> TyBinder mkAnonBinder = Anon |