diff options
author | Ryan Scott <ryan.gl.scott@gmail.com> | 2020-11-05 11:28:53 -0500 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2020-12-18 05:50:33 -0500 |
commit | 7a93435b991513b71174c807b4e99ad90f4e5058 (patch) | |
tree | b73379e691967b81a751462b2b051a91ab0ee2ed | |
parent | 659fcb14937e60510e3eea4c1211ea117419905b (diff) | |
download | haskell-7a93435b991513b71174c807b4e99ad90f4e5058.tar.gz |
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.
-rw-r--r-- | compiler/GHC/Hs/Type.hs | 29 | ||||
-rw-r--r-- | compiler/GHC/Rename/HsType.hs | 53 | ||||
-rw-r--r-- | compiler/GHC/Tc/Deriv/Generate.hs | 121 | ||||
-rw-r--r-- | compiler/GHC/Tc/Gen/HsType.hs | 22 | ||||
-rw-r--r-- | compiler/GHC/Tc/Gen/Sig.hs | 2 | ||||
-rw-r--r-- | compiler/GHC/Tc/TyCl/Instance.hs | 2 | ||||
-rw-r--r-- | testsuite/tests/deriving/should_compile/T14578.stderr | 23 | ||||
-rw-r--r-- | testsuite/tests/deriving/should_compile/T18914.hs | 12 | ||||
-rw-r--r-- | testsuite/tests/deriving/should_compile/all.T | 1 | ||||
m--------- | utils/haddock | 0 |
10 files changed, 211 insertions, 54 deletions
diff --git a/compiler/GHC/Hs/Type.hs b/compiler/GHC/Hs/Type.hs index dde27857ec..1b1e56b314 100644 --- a/compiler/GHC/Hs/Type.hs +++ b/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 diff --git a/compiler/GHC/Rename/HsType.hs b/compiler/GHC/Rename/HsType.hs index 9cf422a92e..34f2cf1ca2 100644 --- a/compiler/GHC/Rename/HsType.hs +++ b/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 diff --git a/compiler/GHC/Tc/Deriv/Generate.hs b/compiler/GHC/Tc/Deriv/Generate.hs index a2ba8d1dbb..3c45c8f379 100644 --- a/compiler/GHC/Tc/Deriv/Generate.hs +++ b/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 _ _ _ diff --git a/compiler/GHC/Tc/Gen/HsType.hs b/compiler/GHC/Tc/Gen/HsType.hs index 6748e8a4c4..5f92272242 100644 --- a/compiler/GHC/Tc/Gen/HsType.hs +++ b/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] diff --git a/compiler/GHC/Tc/Gen/Sig.hs b/compiler/GHC/Tc/Gen/Sig.hs index 64be6780a3..095fefe468 100644 --- a/compiler/GHC/Tc/Gen/Sig.hs +++ b/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 diff --git a/compiler/GHC/Tc/TyCl/Instance.hs b/compiler/GHC/Tc/TyCl/Instance.hs index 8248a87d7f..11a10baf29 100644 --- a/compiler/GHC/Tc/TyCl/Instance.hs +++ b/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] diff --git a/testsuite/tests/deriving/should_compile/T14578.stderr b/testsuite/tests/deriving/should_compile/T14578.stderr index d93f12c34c..6db596396d 100644 --- a/testsuite/tests/deriving/should_compile/T14578.stderr +++ b/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) diff --git a/testsuite/tests/deriving/should_compile/T18914.hs b/testsuite/tests/deriving/should_compile/T18914.hs new file mode 100644 index 0000000000..8d30695cf4 --- /dev/null +++ b/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 diff --git a/testsuite/tests/deriving/should_compile/all.T b/testsuite/tests/deriving/should_compile/all.T index 4e938809be..97c3865f4b 100644 --- a/testsuite/tests/deriving/should_compile/all.T +++ b/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, ['']) diff --git a/utils/haddock b/utils/haddock -Subproject 059acb11d6134ee0d896bcf73c870958557a390 +Subproject c3b276d94e207717731512d1e1f8b59b729b653 |