summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorRyan Scott <ryan.gl.scott@gmail.com>2018-04-19 12:36:42 -0400
committerBen Gamari <ben@smart-cactus.org>2018-04-19 13:18:14 -0400
commitb08a6d75e0440f33260bea5319b8c3f871b42f6e (patch)
treeeeae0a52bc64aac7a1a9e2d83e25053f0b87e243 /compiler
parentcac8be611e7e80ed80e24b15faac9e1ac0a07247 (diff)
downloadhaskell-b08a6d75e0440f33260bea5319b8c3f871b42f6e.tar.gz
Fix #15012 with a well-placed use of Any
Previously, derived `Generic1` instances could have associated `Rep1` type family instances with unbound variables, such as in the following example: ```lang=haskell data T a = MkT (FakeOut a) deriving Generic1 type FakeOut a = Int ==> instance Generic1 T where type Rep1 T = ... (Rec0 (FakeOut a)) ``` Yikes! To avoid this, we simply map the last type variable in a derived `Generic1` instance to `Any`. Test Plan: make test TEST=T15012 Reviewers: bgamari Reviewed By: bgamari Subscribers: simonpj, thomie, carter GHC Trac Issues: #15012 Differential Revision: https://phabricator.haskell.org/D4602
Diffstat (limited to 'compiler')
-rw-r--r--compiler/typecheck/TcGenGenerics.hs36
1 files changed, 35 insertions, 1 deletions
diff --git a/compiler/typecheck/TcGenGenerics.hs b/compiler/typecheck/TcGenGenerics.hs
index 61a432e9dc..9da94280ce 100644
--- a/compiler/typecheck/TcGenGenerics.hs
+++ b/compiler/typecheck/TcGenGenerics.hs
@@ -420,7 +420,15 @@ tc_mkRepFamInsts gk tycon inst_tys =
-- type arguments before generating the Rep/Rep1 instance, since some
-- of the tyvars might have been instantiated when deriving.
-- See Note [Generating a correctly typed Rep instance].
- ; let env = zipTyEnv tyvars inst_args
+ ; let (env_tyvars, env_inst_args)
+ = case gk_ of
+ Gen0_ -> (tyvars, inst_args)
+ Gen1_ last_tv
+ -- See the "wrinkle" in
+ -- Note [Generating a correctly typed Rep instance]
+ -> ( last_tv : tyvars
+ , anyTypeOfKind (tyVarKind last_tv) : inst_args )
+ env = zipTyEnv env_tyvars env_inst_args
in_scope = mkInScopeSet (tyCoVarsOfTypes inst_tys)
subst = mkTvSubst in_scope env
repTy' = substTy subst repTy
@@ -923,6 +931,32 @@ the tyConTyVars of the TyCon to their counterparts in the fully instantiated
type. (For example, using T above as example, you'd map a :-> Int.) We then
apply the substitution to the RHS before generating the instance.
+A wrinkle in all of this: when forming the type variable substitution for
+Generic1 instances, we map the last type variable of the tycon to Any. Why?
+It's because of wily data types like this one (#15012):
+
+ data T a = MkT (FakeOut a)
+ type FakeOut a = Int
+
+If we ignore a, then we'll produce the following Rep1 instance:
+
+ instance Generic1 T where
+ type Rep1 T = ... (Rec0 (FakeOut a))
+ ...
+
+Oh no! Now we have `a` on the RHS, but it's completely unbound. Instead, we
+ensure that `a` is mapped to Any:
+
+ instance Generic1 T where
+ type Rep1 T = ... (Rec0 (FakeOut Any))
+ ...
+
+And now all is good.
+
+Alternatively, we could have avoided this problem by expanding all type
+synonyms on the RHSes of Rep1 instances. But we might blow up the size of
+these types even further by doing this, so we choose not to do so.
+
Note [Handling kinds in a Rep instance]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Because Generic1 is poly-kinded, the representation types were generalized to