diff options
Diffstat (limited to 'compiler/GHC/Core')
-rw-r--r-- | compiler/GHC/Core/DataCon.hs | 33 | ||||
-rw-r--r-- | compiler/GHC/Core/Lint.hs | 2 | ||||
-rw-r--r-- | compiler/GHC/Core/Opt/Simplify.hs | 10 | ||||
-rw-r--r-- | compiler/GHC/Core/Type.hs | 8 |
4 files changed, 43 insertions, 10 deletions
diff --git a/compiler/GHC/Core/DataCon.hs b/compiler/GHC/Core/DataCon.hs index 064cdc866f..01ab6414c3 100644 --- a/compiler/GHC/Core/DataCon.hs +++ b/compiler/GHC/Core/DataCon.hs @@ -250,6 +250,8 @@ in wrapper_reqd in GHC.Types.Id.Make.mkDataConRep. * Type variables may be permuted; see MkId Note [Data con wrappers and GADT syntax] +* Datatype contexts require dropping some dictionary arguments. + See Note [Instantiating stupid theta]. Note [The stupid context] ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -282,7 +284,7 @@ gets inferred type I say the context is "stupid" because the dictionaries passed are immediately discarded -- they do nothing and have no benefit. -(See Note [Instantiating stupid theta] in GHC.Tc.Gen.Head.) +(See Note [Instantiating stupid theta].) It's a flaw in the language. GHC has made some efforts to correct this flaw. In GHC, datatype contexts @@ -326,6 +328,30 @@ Some other notes about stupid contexts: result, dcStupidTheta is always empty for data types defined using GADT syntax. +Note [Instantiating stupid theta] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Consider a data type with a "stupid theta" (see +Note [The stupid context]): + + data Ord a => T a = MkT (Maybe a) + +We want to generate an Ord constraint for every use of MkT; but +we also want to allow visible type application, such as + + MkT @Int + +To achieve this, the wrapper for a data (or newtype) constructor +with a datatype context contains a lambda which drops the dictionary +argments corresponding to the datatype context: + + /\a \(_d:Ord a). MkT @a + +Notice that the wrapper discards the dictionary argument d. +We don't need it; it was only there to generate a Wanted constraint. +(That is why it is stupid.) + +This all happens in GHC.Types.Id.Make.mkDataConRep. + ************************************************************************ * * \subsection{Data constructors} @@ -1449,9 +1475,10 @@ dataConWrapperType :: DataCon -> Type -- mentions the family tycon, not the internal one. dataConWrapperType (MkData { dcUserTyVarBinders = user_tvbs, dcOtherTheta = theta, dcOrigArgTys = arg_tys, - dcOrigResTy = res_ty }) + dcOrigResTy = res_ty, + dcStupidTheta = stupid_theta }) = mkInvisForAllTys user_tvbs $ - mkInvisFunTysMany theta $ + mkInvisFunTysMany (stupid_theta ++ theta) $ mkVisFunTys arg_tys $ res_ty diff --git a/compiler/GHC/Core/Lint.hs b/compiler/GHC/Core/Lint.hs index 0511a4004d..a378f48e98 100644 --- a/compiler/GHC/Core/Lint.hs +++ b/compiler/GHC/Core/Lint.hs @@ -1216,7 +1216,7 @@ checkCanEtaExpand (Var fun_id) args app_ty = ty : go (i+1) bndrs bad_arg_tys :: [Type] - bad_arg_tys = check_args . map fst $ getRuntimeArgTys app_ty + bad_arg_tys = check_args . map (scaledThing . fst) $ getRuntimeArgTys app_ty -- We use 'getRuntimeArgTys' to find all the argument types, -- including those hidden under newtypes. For example, -- if `FunNT a b` is a newtype around `a -> b`, then diff --git a/compiler/GHC/Core/Opt/Simplify.hs b/compiler/GHC/Core/Opt/Simplify.hs index f052bae942..c44fd1d62a 100644 --- a/compiler/GHC/Core/Opt/Simplify.hs +++ b/compiler/GHC/Core/Opt/Simplify.hs @@ -2904,8 +2904,14 @@ doCaseToLet scrut case_bndr | isTyCoVar case_bndr -- Respect GHC.Core = isTyCoArg scrut -- Note [Core type and coercion invariant] - | isUnliftedType (idType case_bndr) - -- OK to call isUnliftedType: scrutinees always have a fixed RuntimeRep (see FRRCase) + | isUnliftedType (exprType scrut) + -- We can call isUnliftedType here: scrutinees always have a fixed RuntimeRep (see FRRCase). + -- Note however that we must check 'scrut' (which is an 'OutExpr') and not 'case_bndr' + -- (which is an 'InId'): see Note [Dark corner with representation polymorphism]. + -- Using `exprType` is typically cheap becuase `scrut` is typically a variable. + -- We could instead use mightBeUnliftedType (idType case_bndr), but that hurts + -- the brain more. Consider that if this test ever turns out to be a perf + -- problem (which seems unlikely). = exprOkForSpeculation scrut | otherwise -- Scrut has a lifted type diff --git a/compiler/GHC/Core/Type.hs b/compiler/GHC/Core/Type.hs index 419c0c8806..7029125768 100644 --- a/compiler/GHC/Core/Type.hs +++ b/compiler/GHC/Core/Type.hs @@ -2153,14 +2153,14 @@ splitPiTys ty = split ty ty [] -- newtype N a = MkN (a -> N a) -- getRuntimeArgTys (N a) == repeat (a, VisArg) -- @ -getRuntimeArgTys :: Type -> [(Type, AnonArgFlag)] +getRuntimeArgTys :: Type -> [(Scaled Type, AnonArgFlag)] getRuntimeArgTys = go where - go :: Type -> [(Type, AnonArgFlag)] + go :: Type -> [(Scaled Type, AnonArgFlag)] go (ForAllTy _ res) = go res - go (FunTy { ft_arg = arg, ft_res = res, ft_af = af }) - = (arg, af) : go res + go (FunTy { ft_mult = w, ft_arg = arg, ft_res = res, ft_af = af }) + = (Scaled w arg, af) : go res go ty | Just ty' <- coreView ty = go ty' |