summaryrefslogtreecommitdiff
path: root/compiler/GHC/Core
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/Core')
-rw-r--r--compiler/GHC/Core/DataCon.hs33
-rw-r--r--compiler/GHC/Core/Lint.hs2
-rw-r--r--compiler/GHC/Core/Opt/Simplify.hs10
-rw-r--r--compiler/GHC/Core/Type.hs8
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'