[Git][ghc/ghc][wip/T18914] Use HsOuterExplicit in instance sigs in deriving-generated code

Ryan Scott gitlab at gitlab.haskell.org
Wed Dec 16 21:57:42 UTC 2020



Ryan Scott pushed to branch wip/T18914 at Glasgow Haskell Compiler / GHC


Commits:
3f4353cf by Ryan Scott at 2020-12-16T16:57:28-05:00
Use HsOuterExplicit in instance sigs in deriving-generated code

Issue #18914 revealed that `GeneralizedNewtypeDeriving` would generate code
that mentions unbound type variables, which is dangerously fragile. The
problem (and fix) is described in the new `Wrinkle: Use HsOuterExplicit`
in `Note [GND and QuantifiedConstraints]`. The gist of it: make sure to
put the top-level `forall`s in `deriving`-generated instance signatures in an
`HsOuterExplicit` to ensure that they scope over the bodies of methods
correctly. A side effect of this process is that it will expand any type
synonyms in the instance signature, which will surface any `forall`s that
are hidden underneath type synonyms (such as in the test case for #18914).

While I was in town, I also performed some maintenance on `NewHsTypeX`, which
powers `GeneralizedNewtypeDeriving`:

* I renamed `NewHsTypeX` to `HsCoreTy`, which more accurately describes its
  intended purpose (#15706). I also made `HsCoreTy` a type synonym instead of
  a newtype, as making it a distinct data type wasn't buying us much.
* To make sure that mistakes similar to #18914 do not occur later, I added an
  additional validity check when renaming `HsCoreTy`s that complains if an
  `HsCoreTy`s contains an out-of-scope type variable. See the new
  `Note [Renaming HsCoreTys]` in `GHC.Rename.HsType` for the details.

Fixes #15706. Fixes #18914. Bumps the `haddock` submodule.

- - - - -


10 changed files:

- compiler/GHC/Hs/Type.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Tc/Deriv/Generate.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Sig.hs
- compiler/GHC/Tc/TyCl/Instance.hs
- testsuite/tests/deriving/should_compile/T14578.stderr
- + testsuite/tests/deriving/should_compile/T18914.hs
- testsuite/tests/deriving/should_compile/all.T
- utils/haddock


Changes:

=====================================
compiler/GHC/Hs/Type.hs
=====================================
@@ -24,7 +24,7 @@ module GHC.Hs.Type (
         HsArrow(..), arrowToHsType,
         hsLinear, hsUnrestricted, isUnrestricted,
 
-        HsType(..), NewHsTypeX(..), LHsType, HsKind, LHsKind,
+        HsType(..), HsCoreTy, LHsType, HsKind, LHsKind,
         HsForAllTelescope(..), HsTyVarBndr(..), LHsTyVarBndr,
         LHsQTyVars(..),
         HsOuterTyVarBndrs(..), HsOuterFamEqnTyVarBndrs, HsOuterSigTyVarBndrs,
@@ -1040,12 +1040,6 @@ data HsType pass
 
       -- For details on above see note [Api annotations] in GHC.Parser.Annotation
 
-  -- | HsCoreTy (XCoreTy pass) Type -- An escape hatch for tunnelling a *closed*
-  --                                -- Core Type through HsSyn.
-  --     -- ^ - 'GHC.Parser.Annotation.AnnKeywordId' : None
-
-      -- For details on above see note [Api annotations] in GHC.Parser.Annotation
-
   | HsExplicitListTy       -- A promoted explicit list
         (XExplicitListTy pass)
         PromotionFlag      -- whether explicitly promoted, for pretty printer
@@ -1078,16 +1072,13 @@ data HsType pass
   | XHsType
       (XXType pass)
 
-data NewHsTypeX
-  = NHsCoreTy Type -- An escape hatch for tunnelling a *closed*
-                   -- Core Type through HsSyn.
-                   -- See also Note [Typechecking NHsCoreTys] in
-                   -- GHC.Tc.Gen.HsType.
-    deriving Data
-      -- ^ - 'GHC.Parser.Annotation.AnnKeywordId' : None
-
-instance Outputable NewHsTypeX where
-  ppr (NHsCoreTy ty) = ppr ty
+-- An escape hatch for tunnelling a Core 'Type' through 'HsType'.
+-- For more details on how this works, see:
+--
+-- * @Note [Renaming HsCoreTys]@ in "GHC.Rename.HsType"
+--
+-- * @Note [Typechecking HsCoreTys]@ in "GHC.Tc.Gen.HsType"
+type HsCoreTy = Type
 
 type instance XForAllTy        (GhcPass _) = NoExtField
 type instance XQualTy          (GhcPass _) = NoExtField
@@ -1125,7 +1116,7 @@ type instance XTyLit           (GhcPass _) = NoExtField
 
 type instance XWildCardTy      (GhcPass _) = NoExtField
 
-type instance XXType         (GhcPass _) = NewHsTypeX
+type instance XXType         (GhcPass _) = HsCoreTy
 
 
 -- Note [Literal source text] in GHC.Types.Basic for SourceText fields in
@@ -2256,7 +2247,7 @@ hsTypeNeedsParens p = go_hs_ty
     go_hs_ty (HsOpTy{})               = p >= opPrec
     go_hs_ty (HsParTy{})              = False
     go_hs_ty (HsDocTy _ (L _ t) _)    = go_hs_ty t
-    go_hs_ty (XHsType (NHsCoreTy ty)) = go_core_ty ty
+    go_hs_ty (XHsType ty)             = go_core_ty ty
 
     go_core_ty (TyVarTy{})    = False
     go_core_ty (AppTy{})      = p >= appPrec


=====================================
compiler/GHC/Rename/HsType.hs
=====================================
@@ -41,6 +41,7 @@ import GHC.Prelude
 
 import {-# SOURCE #-} GHC.Rename.Splice( rnSpliceType )
 
+import GHC.Core.TyCo.FVs ( tyCoVarsOfTypeList )
 import GHC.Driver.Session
 import GHC.Hs
 import GHC.Rename.Env
@@ -50,6 +51,7 @@ import GHC.Rename.Utils  ( HsDocContext(..), inHsDocContext, withHsDocContext
                          , checkShadowedRdrNames )
 import GHC.Rename.Fixity ( lookupFieldFixityRn, lookupFixityRn
                          , lookupTyFixityRn )
+import GHC.Rename.Unbound ( notInScopeErr )
 import GHC.Tc.Utils.Monad
 import GHC.Types.Name.Reader
 import GHC.Builtin.Names
@@ -717,10 +719,20 @@ rnHsTyKi env (HsDocTy _ ty haddock_doc)
   = do { (ty', fvs) <- rnLHsTyKi env ty
        ; return (HsDocTy noExtField ty' haddock_doc, fvs) }
 
-rnHsTyKi _ (XHsType (NHsCoreTy ty))
-  = return (XHsType (NHsCoreTy ty), emptyFVs)
-    -- The emptyFVs probably isn't quite right
-    -- but I don't think it matters
+-- See Note [Renaming HsCoreTys]
+rnHsTyKi env (XHsType ty)
+  = do mapM_ (check_in_scope . nameRdrName) fvs_list
+       return (XHsType ty, fvs)
+  where
+    fvs_list = map getName $ tyCoVarsOfTypeList ty
+    fvs = mkFVs fvs_list
+
+    check_in_scope :: RdrName -> RnM ()
+    check_in_scope rdr_name = do
+      mb_name <- lookupLocalOccRn_maybe rdr_name
+      when (isNothing mb_name) $
+        addErr $ withHsDocContext (rtke_ctxt env) $
+        notInScopeErr rdr_name
 
 rnHsTyKi env ty@(HsExplicitListTy _ ip tys)
   = do { data_kinds <- xoptM LangExt.DataKinds
@@ -744,6 +756,39 @@ rnHsArrow _env (HsLinearArrow u) = return (HsLinearArrow u, emptyFVs)
 rnHsArrow env (HsExplicitMult u p)
   = (\(mult, fvs) -> (HsExplicitMult u mult, fvs)) <$> rnLHsTyKi env p
 
+{-
+Note [Renaming HsCoreTys]
+~~~~~~~~~~~~~~~~~~~~~~~~~
+HsCoreTy is an escape hatch that allows embedding Core Types in HsTypes.
+As such, there's not much to be done in order to rename an HsCoreTy,
+since it's already been renamed to some extent. However, in an attempt to
+detect ill-formed HsCoreTys, the renamer checks to see if all free type
+variables in an HsCoreTy are in scope. To see why this can matter, consider
+this example from #18914:
+
+  type T f = forall a. f a
+
+  class C f where
+    m :: T f
+
+  newtype N f a = MkN (f a)
+    deriving C
+
+Because of #18914, a previous GHC would generate the following code:
+
+  instance C f => C (N f) where
+    m :: T (N f)
+    m = coerce @(f a)   -- The type within @(...) is an HsCoreTy
+               @(N f a) -- So is this
+               (m @f)
+
+There are two HsCoreTys in play—(f a) and (N f a)—both of which have
+`f` and `a` as free type variables. The `f` is in scope from the instance head,
+but `a` is completely unbound, which is what led to #18914. To avoid this sort
+of mistake going forward, the renamer will now detect that `a` is unbound and
+throw an error accordingly.
+-}
+
 --------------
 rnTyVar :: RnTyKiEnv -> RdrName -> RnM Name
 rnTyVar env rdr_name


=====================================
compiler/GHC/Tc/Deriv/Generate.hs
=====================================
@@ -1819,6 +1819,94 @@ a truly higher-rank type like so:
 Then the same situation will arise again. But at least it won't arise for the
 common case of methods with ordinary, prenex-quantified types.
 
+-----
+-- Wrinkle: Use HsOuterExplicit
+-----
+
+One minor complication with the plan above is that we need to ensure that the
+type variables from a method's instance signature properly scope over the body
+of the method. For example, recall:
+
+  instance (C m, forall p q. Coercible p q => Coercible (m p) (m q)) =>
+      C (T m) where
+    join :: forall a. T m (T m a) -> T m a
+    join = coerce @(  m   (m a) ->   m a)
+                  @(T m (T m a) -> T m a)
+                  join
+
+In the example above, it is imperative that the `a` in the instance signature
+for `join` scope over the body of `join` by way of ScopedTypeVariables.
+This might sound obvious, but note that in gen_Newtype_binds, which is
+responsible for generating the code above, the type in `join`'s instance
+signature is given as a Core type, whereas gen_Newtype_binds will eventually
+produce HsBinds (i.e., source Haskell) that is renamed and typechecked. We
+must ensure that `a` is in scope over the body of `join` during renaming
+or else the generated code will be rejected.
+
+In short, we need to convert the instance signature from a Core type to an
+HsType (i.e., a source Haskell type). Two possible options are:
+
+1. Convert the Core type entirely to an HsType (i.e., a source Haskell type).
+2. Embed the entire Core type using HsCoreTy.
+
+Neither option is quite satisfactory:
+
+1. Converting a Core type to an HsType in full generality is surprisingly
+   complicated. Previous versions of GHCs did this, but it was the source of
+   numerous bugs (see #14579 and #16518, for instance).
+2. While HsCoreTy is much less complicated that option (1), it's not quite
+   what we want. In order for `a` to be in scope over the body of `join` during
+   renaming, the `forall` must be contained in an HsOuterExplicit.
+   (See Note [Lexically scoped type variables] in GHC.Hs.Type.) HsCoreTy
+   bypasses HsOuterExplicit, so this won't work either.
+
+As a compromise, we adopt a combination of the two options above:
+
+* Split apart the top-level ForAllTys in the instance signature's Core type,
+* Convert the top-level ForAllTys to an HsOuterExplicit, and
+* Embed the remainder of the Core type in an HsCoreTy.
+
+This retains most of the simplicity of option (2) while still ensuring that
+the type variables are correctly scoped.
+
+Note that splitting apart top-level ForAllTys will expand any type synonyms
+in the Core type itself. This ends up being important to fix a corner case
+observed in #18914. Consider this example:
+
+  type T f = forall a. f a
+
+  class C f where
+    m :: T f
+
+  newtype N f a = MkN (f a)
+    deriving C
+
+What code should `deriving C` generate? It will have roughly the following
+shape:
+
+  instance C f => C (N f) where
+    m :: T (N f)
+    m = coerce @(...) (...) (m @f)
+
+At a minimum, we must instantiate `coerce` with `@(T f)` and `@(T (N f))`, but
+with the `forall`s removed in order to make them monotypes. However, the
+`forall` is hidden underneath the `T` type synonym, so we must first expand `T`
+before we can strip of the `forall`. Expanding `T`, we get
+`coerce @(forall a. f a) @(forall a. N f a)`, and after omitting the `forall`s,
+we get `coerce @(f a) @(N f a)`.
+
+We can't stop there, however, or else we would end up with this code:
+
+  instance C f => C (N f) where
+    m :: T (N f)
+    m = coerce @(f a) @(N f a) (m @f)
+
+Notice that the type variable `a` is completely unbound. In order to make sure
+that `a` is in scope, we must /also/ expand the `T` in `m :: T (N f)` to get
+`m :: forall a. N f a`. Fortunately, we will do just that in the plan outlined
+above, since when we split off the top-level ForAllTys in the instance
+signature, we must first expand the T type synonym.
+
 Note [GND and ambiguity]
 ~~~~~~~~~~~~~~~~~~~~~~~~
 We make an effort to make the code generated through GND be robust w.r.t.
@@ -1891,13 +1979,30 @@ gen_Newtype_binds loc cls inst_tvs inst_tys rhs_ty
         , -- The derived instance signature, e.g.,
           --
           --   op :: forall c. a -> [T x] -> c -> Int
+          --
+          -- Make sure that `forall c` is in an HsOuterExplicit so that it
+          -- scopes over the body of `op`. See "Wrinkle: Use HsOuterExplicit" in
+          -- Note [GND and QuantifiedConstraints].
           L loc $ ClassOpSig noExtField False [loc_meth_RDR]
-                $ L loc $ mkHsImplicitSigType $ nlHsCoreTy to_ty
+                $ L loc $ mkHsExplicitSigType
+                            (map mk_hs_tvb to_tvbs)
+                            (nlHsCoreTy to_rho)
         )
       where
         Pair from_ty to_ty = mkCoerceClassMethEqn cls inst_tvs inst_tys rhs_ty meth_id
-        (_, _, from_tau) = tcSplitSigmaTy from_ty
-        (_, _, to_tau)   = tcSplitSigmaTy to_ty
+        (_, _, from_tau)  = tcSplitSigmaTy from_ty
+        (to_tvbs, to_rho) = tcSplitForAllInvisTVBinders to_ty
+        (_, to_tau)       = tcSplitPhiTy to_rho
+        -- The use of tcSplitForAllInvisTVBinders above expands type synonyms,
+        -- which is important to ensure correct type variable scoping.
+        -- See "Wrinkle: Use HsOuterExplicit" in
+        -- Note [GND and QuantifiedConstraints].
+
+        mk_hs_tvb :: VarBndr TyVar flag -> LHsTyVarBndr flag GhcPs
+        mk_hs_tvb (Bndr tv flag) = noLoc $ KindedTyVar noExtField
+                                                       flag
+                                                       (noLoc (getRdrName tv))
+                                                       (nlHsCoreTy (tyVarKind tv))
 
         meth_RDR = getRdrName meth_id
         loc_meth_RDR = L loc meth_RDR
@@ -1950,8 +2055,8 @@ nlHsAppType e s = noLoc (HsAppType noExtField e hs_ty)
   where
     hs_ty = mkHsWildCardBndrs $ parenthesizeHsType appPrec $ nlHsCoreTy s
 
-nlHsCoreTy :: Type -> LHsType GhcPs
-nlHsCoreTy = noLoc . XHsType . NHsCoreTy
+nlHsCoreTy :: HsCoreTy -> LHsType GhcPs
+nlHsCoreTy = noLoc . XHsType
 
 mkCoerceClassMethEqn :: Class   -- the class being derived
                      -> [TyVar] -- the tvs in the instance head (this includes
@@ -2079,15 +2184,15 @@ genAuxBindSpecDup loc original_rdr_name dup_spec
 genAuxBindSpecSig :: SrcSpan -> AuxBindSpec -> LHsSigWcType GhcPs
 genAuxBindSpecSig loc spec = case spec of
   DerivCon2Tag tycon _
-    -> mk_sig $ L loc $ XHsType $ NHsCoreTy $
+    -> mk_sig $ L loc $ XHsType $
        mkSpecSigmaTy (tyConTyVars tycon) (tyConStupidTheta tycon) $
        mkParentType tycon `mkVisFunTyMany` intPrimTy
   DerivTag2Con tycon _
     -> mk_sig $ L loc $
-       XHsType $ NHsCoreTy $ mkSpecForAllTys (tyConTyVars tycon) $
+       XHsType $ mkSpecForAllTys (tyConTyVars tycon) $
        intTy `mkVisFunTyMany` mkParentType tycon
   DerivMaxTag _ _
-    -> mk_sig (L loc (XHsType (NHsCoreTy intTy)))
+    -> mk_sig (L loc (XHsType intTy))
   DerivDataDataType _ _ _
     -> mk_sig (nlHsTyVar dataType_RDR)
   DerivDataConstr _ _ _


=====================================
compiler/GHC/Tc/Gen/HsType.hs
=====================================
@@ -947,8 +947,8 @@ tc_infer_hs_type mode (HsSpliceTy _ (HsSpliced _ _ (HsSplicedTy ty)))
 
 tc_infer_hs_type mode (HsDocTy _ ty _) = tc_infer_lhs_type mode ty
 
--- See Note [Typechecking NHsCoreTys]
-tc_infer_hs_type _ (XHsType (NHsCoreTy ty))
+-- See Note [Typechecking HsCoreTys]
+tc_infer_hs_type _ (XHsType ty)
   = do env <- getLclEnv
        -- Raw uniques since we go from NameEnv to TvSubstEnv.
        let subst_prs :: [(Unique, TcTyVar)]
@@ -972,21 +972,21 @@ tc_infer_hs_type mode other_ty
        ; return (ty', kv) }
 
 {-
-Note [Typechecking NHsCoreTys]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-NHsCoreTy is an escape hatch that allows embedding Core Types in HsTypes.
-As such, there's not much to be done in order to typecheck an NHsCoreTy,
+Note [Typechecking HsCoreTys]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+HsCoreTy is an escape hatch that allows embedding Core Types in HsTypes.
+As such, there's not much to be done in order to typecheck an HsCoreTy,
 since it's already been typechecked to some extent. There is one thing that
 we must do, however: we must substitute the type variables from the tcl_env.
 To see why, consider GeneralizedNewtypeDeriving, which is one of the main
-clients of NHsCoreTy (example adapted from #14579):
+clients of HsCoreTy (example adapted from #14579):
 
   newtype T a = MkT a deriving newtype Eq
 
 This will produce an InstInfo GhcPs that looks roughly like this:
 
   instance forall a_1. Eq a_1 => Eq (T a_1) where
-    (==) = coerce @(  a_1 ->   a_1 -> Bool) -- The type within @(...) is an NHsCoreTy
+    (==) = coerce @(  a_1 ->   a_1 -> Bool) -- The type within @(...) is an HsCoreTy
                   @(T a_1 -> T a_1 -> Bool) -- So is this
                   (==)
 
@@ -1002,9 +1002,9 @@ environment (tcl_env) with [a_1 :-> a_2]. This gives us:
 
 To ensure that the body of this instance is well scoped, every occurrence of
 the `a` type variable should refer to a_2, the new skolem. However, the
-NHsCoreTys mention a_1, not a_2. Luckily, the tcl_env provides exactly the
+HsCoreTys mention a_1, not a_2. Luckily, the tcl_env provides exactly the
 substitution we need ([a_1 :-> a_2]) to fix up the scoping. We apply this
-substitution to each NHsCoreTy and all is well:
+substitution to each HsCoreTy and all is well:
 
   instance forall a_2. Eq a_2 => Eq (T a_2) where
     (==) = coerce @(  a_2 ->   a_2 -> Bool)
@@ -1206,7 +1206,7 @@ tc_hs_type mode ty@(HsAppTy {})            ek = tc_infer_hs_type_ek mode ty ek
 tc_hs_type mode ty@(HsAppKindTy{})         ek = tc_infer_hs_type_ek mode ty ek
 tc_hs_type mode ty@(HsOpTy {})             ek = tc_infer_hs_type_ek mode ty ek
 tc_hs_type mode ty@(HsKindSig {})          ek = tc_infer_hs_type_ek mode ty ek
-tc_hs_type mode ty@(XHsType (NHsCoreTy{})) ek = tc_infer_hs_type_ek mode ty ek
+tc_hs_type mode ty@(XHsType {})            ek = tc_infer_hs_type_ek mode ty ek
 
 {-
 Note [Variable Specificity and Forall Visibility]


=====================================
compiler/GHC/Tc/Gen/Sig.hs
=====================================
@@ -291,7 +291,7 @@ no_anon_wc_ty lty = go lty
       HsTyLit{} -> True
       HsTyVar{} -> True
       HsStarTy{} -> True
-      XHsType (NHsCoreTy{}) -> True      -- Core type, which does not have any wildcard
+      XHsType{} -> True       -- HsCoreTy, which does not have any wildcard
 
     gos = all go
 


=====================================
compiler/GHC/Tc/TyCl/Instance.hs
=====================================
@@ -2082,7 +2082,7 @@ mkDefMethBind dfun_id clas sel_id dm_name
 
     mk_vta :: LHsExpr GhcRn -> Type -> LHsExpr GhcRn
     mk_vta fun ty = noLoc (HsAppType noExtField fun (mkEmptyWildCardBndrs $ nlHsParTy
-                                                $ noLoc $ XHsType $ NHsCoreTy ty))
+                                                $ noLoc $ XHsType ty))
        -- NB: use visible type application
        -- See Note [Default methods in instances]
 


=====================================
testsuite/tests/deriving/should_compile/T14578.stderr
=====================================
@@ -9,9 +9,8 @@ Derived class instances:
     GHC.Base.sconcat ::
       GHC.Base.NonEmpty (T14578.Wat f g a) -> T14578.Wat f g a
     GHC.Base.stimes ::
-      forall b.
-      GHC.Real.Integral b =>
-      b -> T14578.Wat f g a -> T14578.Wat f g a
+      forall (b :: *).
+      GHC.Real.Integral b => b -> T14578.Wat f g a -> T14578.Wat f g a
     (GHC.Base.<>)
       = GHC.Prim.coerce
           @(T14578.App (Data.Functor.Compose.Compose f g) a
@@ -38,8 +37,10 @@ Derived class instances:
   instance GHC.Base.Functor f =>
            GHC.Base.Functor (T14578.App f) where
     GHC.Base.fmap ::
-      forall a b. (a -> b) -> T14578.App f a -> T14578.App f b
-    (GHC.Base.<$) :: forall a b. a -> T14578.App f b -> T14578.App f a
+      forall (a :: *) (b :: *).
+      (a -> b) -> T14578.App f a -> T14578.App f b
+    (GHC.Base.<$) ::
+      forall (a :: *) (b :: *). a -> T14578.App f b -> T14578.App f a
     GHC.Base.fmap
       = GHC.Prim.coerce
           @((a -> b) -> f a -> f b)
@@ -51,17 +52,19 @@ Derived class instances:
   
   instance GHC.Base.Applicative f =>
            GHC.Base.Applicative (T14578.App f) where
-    GHC.Base.pure :: forall a. a -> T14578.App f a
+    GHC.Base.pure :: forall (a :: *). a -> T14578.App f a
     (GHC.Base.<*>) ::
-      forall a b.
+      forall (a :: *) (b :: *).
       T14578.App f (a -> b) -> T14578.App f a -> T14578.App f b
     GHC.Base.liftA2 ::
-      forall a b c.
+      forall (a :: *) (b :: *) (c :: *).
       (a -> b -> c) -> T14578.App f a -> T14578.App f b -> T14578.App f c
     (GHC.Base.*>) ::
-      forall a b. T14578.App f a -> T14578.App f b -> T14578.App f b
+      forall (a :: *) (b :: *).
+      T14578.App f a -> T14578.App f b -> T14578.App f b
     (GHC.Base.<*) ::
-      forall a b. T14578.App f a -> T14578.App f b -> T14578.App f a
+      forall (a :: *) (b :: *).
+      T14578.App f a -> T14578.App f b -> T14578.App f a
     GHC.Base.pure
       = GHC.Prim.coerce
           @(a -> f a) @(a -> T14578.App f a) (GHC.Base.pure @f)


=====================================
testsuite/tests/deriving/should_compile/T18914.hs
=====================================
@@ -0,0 +1,12 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE RankNTypes #-}
+module T18914 where
+
+type T f = forall a. f a
+
+class C f where
+  m1 :: T f
+  m2 :: forall a. f a
+
+newtype N f a = MkN (f a)
+  deriving C


=====================================
testsuite/tests/deriving/should_compile/all.T
=====================================
@@ -127,3 +127,4 @@ test('T17339', normal, compile,
 test('T17880', normal, compile, [''])
 test('T18055', normal, compile, [''])
 test('T18321', normal, compile, [''])
+test('T18914', normal, compile, [''])


=====================================
utils/haddock
=====================================
@@ -1 +1 @@
-Subproject commit 059acb11d6134ee0d896bcf73c870958557a3909
+Subproject commit c3b276d94e207717731512d1e1f8b59b729b653a



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/3f4353cfc7951349648d0047eece89c5d773e315

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/3f4353cfc7951349648d0047eece89c5d773e315
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20201216/10a7cc5e/attachment-0001.html>


More information about the ghc-commits mailing list