[Git][ghc/ghc][wip/T25661] Fix a buglet in tcSplitForAllTyVarsReqTVBindersN
Simon Peyton Jones (@simonpj)
gitlab at gitlab.haskell.org
Fri Jan 17 21:58:11 UTC 2025
Simon Peyton Jones pushed to branch wip/T25661 at Glasgow Haskell Compiler / GHC
Commits:
98e06512 by Simon Peyton Jones at 2025-01-17T21:57:18+00:00
Fix a buglet in tcSplitForAllTyVarsReqTVBindersN
The problem was that an equation in `split` had two guards (one about
visiblity and one about `n_req`). So it fell thorugh if /either/
was False. But the next equation then assumed an invisible binder.
Simple bug, easily fixed. Fixes #25661.
- - - - -
7 changed files:
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Tc/Gen/Match.hs
- compiler/GHC/Tc/Utils/TcType.hs
- compiler/GHC/Types/Var.hs
- + testsuite/tests/polykinds/T25661.hs
- + testsuite/tests/polykinds/T25661.stderr
- testsuite/tests/polykinds/all.T
Changes:
=====================================
compiler/GHC/Core/TyCo/Rep.hs
=====================================
@@ -155,11 +155,13 @@ data Type
| ForAllTy -- See Note [ForAllTy]
{-# UNPACK #-} !ForAllTyBinder
- Type -- ^ A Π type.
- -- See Note [Why ForAllTy can quantify over a coercion variable]
- -- INVARIANT: If the binder is a coercion variable, it must
- -- be mentioned in the Type.
- -- See Note [Unused coercion variable in ForAllTy]
+ -- ForAllTyBinder: see GHC.Types.Var
+ -- Note [VarBndrs, ForAllTyBinders, TyConBinders, and visibility]
+ Type
+ -- INVARIANT: If the binder is a coercion variable, it must
+ -- be mentioned in the Type.
+ -- See Note [Unused coercion variable in ForAllTy]
+ -- See Note [Why ForAllTy can quantify over a coercion variable]
| FunTy -- ^ FUN m t1 t2 Very common, so an important special case
-- See Note [Function types]
=====================================
compiler/GHC/Tc/Gen/Match.hs
=====================================
@@ -120,13 +120,17 @@ tcFunBindMatches ctxt fun_name mult matches invis_pat_tys exp_ty
-- Makes sure that if the binding is unrestricted, it counts as
-- consuming its rhs Many times.
- do { traceTc "tcFunBindMatches 2" (vcat [ pprUserTypeCtxt ctxt, ppr invis_pat_tys
- , ppr pat_tys $$ ppr rhs_ty ])
+ do { traceTc "tcFunBindMatches 2" $
+ vcat [ text "ctxt:" <+> pprUserTypeCtxt ctxt
+ , text "arity:" <+> ppr arity
+ , text "invis_pat_tys:" <+> ppr invis_pat_tys
+ , text "pat_tys:" <+> ppr pat_tys
+ , text "rhs_ty:" <+> ppr rhs_ty ]
; tcMatches tcBody (invis_pat_tys ++ pat_tys) rhs_ty matches }
; return (wrap_fun, r) }
where
- herald = ExpectedFunTyMatches (NameThing fun_name) matches
+ herald = ExpectedFunTyMatches (NameThing fun_name) matches
funBindPrecondition :: MatchGroup GhcRn (LHsExpr GhcRn) -> Bool
funBindPrecondition (MG { mg_alts = L _ alts })
=====================================
compiler/GHC/Tc/Utils/TcType.hs
=====================================
@@ -1490,8 +1490,10 @@ tcSplitForAllTyVarsReqTVBindersN n_req ty
= split n_req ty ty []
where
split n_req _orig_ty (ForAllTy b@(Bndr _ argf) ty) bs
- | isVisibleForAllTyFlag argf, n_req > 0 = split (n_req - 1) ty ty (b:bs)
- | otherwise = split n_req ty ty (b:bs)
+ | isVisibleForAllTyFlag argf, n_req > 0 -- Split off a visible forall
+ = split (n_req - 1) ty ty (b:bs)
+ | isInvisibleForAllTyFlag argf -- Split off an invisible forall,
+ = split n_req ty ty (b:bs) -- even if n_req=0, i.e. the trailing ones
split n_req orig_ty ty bs | Just ty' <- coreView ty = split n_req orig_ty ty' bs
split n_req orig_ty _ty bs = (n_req, reverse bs, orig_ty)
@@ -1975,7 +1977,7 @@ isSigmaTy :: TcType -> Bool
-- forall a. blah
-- Eq a => blah
-- ?x::Int => blah
--- But not
+-- But NOT
-- forall a -> blah
isSigmaTy (ForAllTy (Bndr _ af) _) = isInvisibleForAllTyFlag af
isSigmaTy (FunTy { ft_af = af }) = isInvisibleFunArg af
=====================================
compiler/GHC/Types/Var.hs
=====================================
@@ -648,6 +648,7 @@ data VarBndr var argf = Bndr var argf
-- A 'ForAllTyBinder' is the binder of a ForAllTy
-- It's convenient to define this synonym here rather its natural
-- home in "GHC.Core.TyCo.Rep", because it's used in GHC.Core.DataCon.hs-boot
+-- See Note [VarBndrs, ForAllTyBinders, TyConBinders, and visibility]
--
-- A 'TyVarBinder' is a binder with only TyVar
type ForAllTyBinder = VarBndr TyCoVar ForAllTyFlag
=====================================
testsuite/tests/polykinds/T25661.hs
=====================================
@@ -0,0 +1,38 @@
+{-# Language TypeFamilyDependencies #-}
+{-# Language RequiredTypeArguments #-}
+module T25661 where
+
+import Data.Kind
+import Control.Category (Category(id, (.)))
+import Prelude hiding (id, (.))
+
+type Cat :: Type -> Type
+type Cat k = k -> k -> Type
+-- type Op :: (k -> j -> Type) -> (j -> k -> Type)
+-- newtype Op cat b a = Op (cat a b)
+
+-- instance Category cat => Category (Op @k @k cat) where
+-- id = Op id
+-- Op f . Op g = Op (g . f)
+
+type NaturalTransformation :: Cat s -> Cat t -> Cat (s -> t)
+data NaturalTransformation src tgt f g where
+ -- NaturalTransformationId :: NaturalTransformation src tgt f f
+ NaturalTransformation :: (FunctorOf src tgt f, FunctorOf src tgt g) => { getNaturalTransformation :: forall x. f x `tgt` g x } -> NaturalTransformation src tgt f g
+
+type
+ FunctorOf :: Cat s -> Cat t -> (s -> t) -> Constraint
+class (NewFunctor f, Source f ~ src, Target f ~ tgt) => FunctorOf src tgt f
+instance (NewFunctor f, Source f ~ src, Target f ~ tgt) => FunctorOf src tgt f
+
+type
+ NewFunctor :: (s -> t) -> Constraint
+class (Category (Source f), Category (Target f)) => NewFunctor (f :: s -> t) where
+ type Source (f :: s -> t) :: Cat s
+ type Target (f :: s -> t) :: Cat t
+ newmap :: Source f a a' -> Target f (f a) (f a')
+
+
+newmapVis :: NewFunctor f => forall source -> source ~ Source f
+ => forall target -> target ~ Target f => source a a' -> target (f a) (f a')
+newmapVis source = undefined
=====================================
testsuite/tests/polykinds/T25661.stderr
=====================================
@@ -0,0 +1,17 @@
+T25661.hs:38:20: error: [GHC-91028]
+ • Couldn't match expected type ‘forall (target :: Cat t) ->
+ (target ~ Target f) => source a a' -> target (f a) (f a')’
+ with actual type ‘a0’
+ Cannot instantiate unification variable ‘a0’
+ with a type involving polytypes:
+ forall (target :: Cat t) ->
+ (target ~ Target f) => source a a' -> target (f a) (f a')
+ • In the expression: undefined
+ In an equation for ‘newmapVis’: newmapVis source = undefined
+ • Relevant bindings include
+ newmapVis :: forall (source :: Cat s) ->
+ (source ~ Source f) =>
+ forall (target :: Cat t) ->
+ (target ~ Target f) => source a a' -> target (f a) (f a')
+ (bound at T25661.hs:38:1)
+
=====================================
testsuite/tests/polykinds/all.T
=====================================
@@ -247,3 +247,4 @@ test('T24083', normal, compile_fail, [''])
test('T24083a', normal, compile, [''])
test('T24686', normal, compile_fail, [''])
test('T24686a', normal, compile_fail, [''])
+test('T25661', normal, compile_fail, [''])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/98e065128cd723bfa5edf13c9bc2f03149770938
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/98e065128cd723bfa5edf13c9bc2f03149770938
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/20250117/f4c55266/attachment-0001.html>
More information about the ghc-commits
mailing list