Simon Peyton Jones pushed to branch wip/T26115 at Glasgow Haskell Compiler / GHC
Commits:
-
13986e8d
by Simon Peyton Jones at 2025-07-21T00:18:42+01:00
4 changed files:
- compiler/GHC/Tc/Deriv.hs
- compiler/GHC/Tc/Deriv/Infer.hs
- compiler/GHC/Tc/Deriv/Utils.hs
- testsuite/tests/deriving/should_compile/T20815.hs
Changes:
| ... | ... | @@ -1432,13 +1432,13 @@ See Note [Eta reduction for data families] in GHC.Core.Coercion.Axiom |
| 1432 | 1432 | -- EarlyDerivSpec from it.
|
| 1433 | 1433 | mk_eqn_from_mechanism :: DerivSpecMechanism -> DerivM EarlyDerivSpec
|
| 1434 | 1434 | mk_eqn_from_mechanism mechanism
|
| 1435 | - = do DerivEnv { denv_overlap_mode = overlap_mode
|
|
| 1436 | - , denv_tvs = tvs
|
|
| 1437 | - , denv_cls = cls
|
|
| 1438 | - , denv_inst_tys = inst_tys
|
|
| 1439 | - , denv_ctxt = deriv_ctxt
|
|
| 1440 | - , denv_skol_info = skol_info
|
|
| 1441 | - , denv_warn = warn } <- ask
|
|
| 1435 | + = do env@(DerivEnv { denv_overlap_mode = overlap_mode
|
|
| 1436 | + , denv_tvs = tvs
|
|
| 1437 | + , denv_cls = cls
|
|
| 1438 | + , denv_inst_tys = inst_tys
|
|
| 1439 | + , denv_ctxt = deriv_ctxt
|
|
| 1440 | + , denv_skol_info = skol_info
|
|
| 1441 | + , denv_warn = warn }) <- ask
|
|
| 1442 | 1442 | user_ctxt <- askDerivUserTypeCtxt
|
| 1443 | 1443 | doDerivInstErrorChecks1 mechanism
|
| 1444 | 1444 | loc <- lift getSrcSpanM
|
| ... | ... | @@ -1446,7 +1446,7 @@ mk_eqn_from_mechanism mechanism |
| 1446 | 1446 | case deriv_ctxt of
|
| 1447 | 1447 | InferContext wildcard ->
|
| 1448 | 1448 | do { (inferred_constraints, tvs', inst_tys', mechanism')
|
| 1449 | - <- inferConstraints mechanism
|
|
| 1449 | + <- inferConstraints mechanism env
|
|
| 1450 | 1450 | ; return $ InferTheta $ DS
|
| 1451 | 1451 | { ds_loc = loc
|
| 1452 | 1452 | , ds_name = dfun_name, ds_tvs = tvs'
|
| ... | ... | @@ -66,7 +66,7 @@ import Data.Maybe |
| 66 | 66 | |
| 67 | 67 | ----------------------
|
| 68 | 68 | |
| 69 | -inferConstraints :: DerivSpecMechanism
|
|
| 69 | +inferConstraints :: DerivSpecMechanism -> DerivEnv
|
|
| 70 | 70 | -> DerivM (ThetaSpec, [TyVar], [TcType], DerivSpecMechanism)
|
| 71 | 71 | -- inferConstraints figures out the constraints needed for the
|
| 72 | 72 | -- instance declaration generated by a 'deriving' clause on a
|
| ... | ... | @@ -83,12 +83,12 @@ inferConstraints :: DerivSpecMechanism |
| 83 | 83 | -- Generate a sufficiently large set of constraints that typechecking the
|
| 84 | 84 | -- generated method definitions should succeed. This set will be simplified
|
| 85 | 85 | -- before being used in the instance declaration
|
| 86 | -inferConstraints mechanism
|
|
| 87 | - = do { DerivEnv { denv_tvs = tvs
|
|
| 88 | - , denv_cls = main_cls
|
|
| 89 | - , denv_inst_tys = inst_tys } <- ask
|
|
| 90 | - ; wildcard <- isStandaloneWildcardDeriv
|
|
| 91 | - ; let infer_constraints :: DerivM (ThetaSpec, [TyVar], [TcType], DerivSpecMechanism)
|
|
| 86 | +inferConstraints mechanism (DerivEnv { denv_ctxt = ctxt
|
|
| 87 | + , denv_tvs = tvs
|
|
| 88 | + , denv_cls = main_cls
|
|
| 89 | + , denv_inst_tys = inst_tys })
|
|
| 90 | + = do { let wildcard = isStandaloneWildcardDeriv ctxt
|
|
| 91 | + infer_constraints :: DerivM (ThetaSpec, [TyVar], [TcType], DerivSpecMechanism)
|
|
| 92 | 92 | infer_constraints =
|
| 93 | 93 | case mechanism of
|
| 94 | 94 | DerivSpecStock{dsm_stock_dit = dit}
|
| ... | ... | @@ -169,12 +169,12 @@ inferConstraintsStock dit@(DerivInstTys { dit_cls_tys = cls_tys |
| 169 | 169 | , dit_tc_args = tc_args
|
| 170 | 170 | , dit_rep_tc = rep_tc
|
| 171 | 171 | , dit_rep_tc_args = rep_tc_args })
|
| 172 | - = do DerivEnv { denv_tvs = tvs
|
|
| 172 | + = do DerivEnv { denv_ctxt = ctxt
|
|
| 173 | + , denv_tvs = tvs
|
|
| 173 | 174 | , denv_cls = main_cls
|
| 174 | 175 | , denv_inst_tys = inst_tys } <- ask
|
| 175 | - wildcard <- isStandaloneWildcardDeriv
|
|
| 176 | - |
|
| 177 | - let inst_ty = mkTyConApp tc tc_args
|
|
| 176 | + let wildcard = isStandaloneWildcardDeriv ctxt
|
|
| 177 | + inst_ty = mkTyConApp tc tc_args
|
|
| 178 | 178 | tc_binders = tyConBinders rep_tc
|
| 179 | 179 | choose_level bndr
|
| 180 | 180 | | isNamedTyConBinder bndr = KindLevel
|
| ... | ... | @@ -370,13 +370,14 @@ inferConstraintsStock dit@(DerivInstTys { dit_cls_tys = cls_tys |
| 370 | 370 | -- derived instance context.
|
| 371 | 371 | inferConstraintsAnyclass :: DerivM ThetaSpec
|
| 372 | 372 | inferConstraintsAnyclass
|
| 373 | - = do { DerivEnv { denv_cls = cls
|
|
| 373 | + = do { DerivEnv { denv_ctxt = ctxt
|
|
| 374 | + , denv_cls = cls
|
|
| 374 | 375 | , denv_inst_tys = inst_tys } <- ask
|
| 375 | 376 | ; let gen_dms = [ (sel_id, dm_ty)
|
| 376 | 377 | | (sel_id, Just (_, GenericDM dm_ty)) <- classOpItems cls ]
|
| 377 | - ; wildcard <- isStandaloneWildcardDeriv
|
|
| 378 | 378 | |
| 379 | - ; let meth_pred :: (Id, Type) -> PredSpec
|
|
| 379 | + ; let wildcard = isStandaloneWildcardDeriv ctxt
|
|
| 380 | + meth_pred :: (Id, Type) -> PredSpec
|
|
| 380 | 381 | -- (Id,Type) are the selector Id and the generic default method type
|
| 381 | 382 | -- NB: the latter is /not/ quantified over the class variables
|
| 382 | 383 | -- See Note [Gathering and simplifying constraints for DeriveAnyClass]
|
| ... | ... | @@ -408,10 +409,10 @@ inferConstraintsAnyclass |
| 408 | 409 | inferConstraintsCoerceBased :: [Type] -> Type
|
| 409 | 410 | -> DerivM ThetaSpec
|
| 410 | 411 | inferConstraintsCoerceBased cls_tys rep_ty = do
|
| 411 | - DerivEnv { denv_tvs = tvs
|
|
| 412 | + DerivEnv { denv_ctxt = ctxt
|
|
| 413 | + , denv_tvs = tvs
|
|
| 412 | 414 | , denv_cls = cls
|
| 413 | 415 | , denv_inst_tys = inst_tys } <- ask
|
| 414 | - sa_wildcard <- isStandaloneWildcardDeriv
|
|
| 415 | 416 | let -- rep_ty might come from:
|
| 416 | 417 | -- GeneralizedNewtypeDeriving / DerivSpecNewtype:
|
| 417 | 418 | -- the underlying type of the newtype ()
|
| ... | ... | @@ -426,6 +427,7 @@ inferConstraintsCoerceBased cls_tys rep_ty = do |
| 426 | 427 | -- we are going to get all the methods for the final
|
| 427 | 428 | -- dictionary
|
| 428 | 429 | deriv_origin = mkDerivOrigin sa_wildcard
|
| 430 | + sa_wildcard = isStandaloneWildcardDeriv ctxt
|
|
| 429 | 431 | |
| 430 | 432 | -- Next we collect constraints for the class methods
|
| 431 | 433 | -- If there are no methods, we don't need any constraints
|
| ... | ... | @@ -574,7 +576,7 @@ Consider the `deriving Alt` part of this example (from the passing part of |
| 574 | 576 | T20815a):
|
| 575 | 577 | |
| 576 | 578 | class Alt f where
|
| 577 | - some :: Applicative f => f a -> f [a]
|
|
| 579 | + some :: forall a. Applicative f => f a -> f [a]
|
|
| 578 | 580 | |
| 579 | 581 | newtype T f a = T (f a) deriving Alt
|
| 580 | 582 |
| ... | ... | @@ -35,11 +35,11 @@ import GHC.Tc.Deriv.Generate |
| 35 | 35 | import GHC.Tc.Deriv.Functor
|
| 36 | 36 | import GHC.Tc.Deriv.Generics
|
| 37 | 37 | import GHC.Tc.Errors.Types
|
| 38 | -import GHC.Tc.Types.Constraint (WantedConstraints, mkNonCanonical)
|
|
| 38 | +import GHC.Tc.Types.Constraint (WantedConstraints, mkNonCanonical, mkSimpleWC)
|
|
| 39 | 39 | import GHC.Tc.Types.Origin
|
| 40 | 40 | import GHC.Tc.Utils.Monad
|
| 41 | 41 | import GHC.Tc.Utils.TcType
|
| 42 | -import GHC.Tc.Utils.Unify (tcSubTypeSigma)
|
|
| 42 | +import GHC.Tc.Utils.Unify (tcSubTypeSigma, buildImplicationFor)
|
|
| 43 | 43 | import GHC.Tc.Zonk.Type
|
| 44 | 44 | |
| 45 | 45 | import GHC.Core.Class
|
| ... | ... | @@ -71,7 +71,6 @@ import GHC.Utils.Error |
| 71 | 71 | import GHC.Utils.Unique (sameUnique)
|
| 72 | 72 | |
| 73 | 73 | import Control.Monad.Trans.Reader
|
| 74 | -import Data.Foldable (traverse_)
|
|
| 75 | 74 | import Data.Maybe
|
| 76 | 75 | import qualified GHC.LanguageExtensions as LangExt
|
| 77 | 76 | import GHC.Data.List.SetOps (assocMaybe)
|
| ... | ... | @@ -92,12 +91,9 @@ isStandaloneDeriv = asks (go . denv_ctxt) |
| 92 | 91 | -- | Is GHC processing a standalone deriving declaration with an
|
| 93 | 92 | -- extra-constraints wildcard as the context?
|
| 94 | 93 | -- (e.g., @deriving instance _ => Eq (Foo a)@)
|
| 95 | -isStandaloneWildcardDeriv :: DerivM Bool
|
|
| 96 | -isStandaloneWildcardDeriv = asks (go . denv_ctxt)
|
|
| 97 | - where
|
|
| 98 | - go :: DerivContext -> Bool
|
|
| 99 | - go (InferContext wildcard) = isJust wildcard
|
|
| 100 | - go (SupplyContext {}) = False
|
|
| 94 | +isStandaloneWildcardDeriv :: DerivContext -> Bool
|
|
| 95 | +isStandaloneWildcardDeriv (InferContext wildcard) = isJust wildcard
|
|
| 96 | +isStandaloneWildcardDeriv (SupplyContext {}) = False
|
|
| 101 | 97 | |
| 102 | 98 | -- | Return 'InstDeclCtxt' if processing with a standalone @deriving@
|
| 103 | 99 | -- declaration or 'DerivClauseCtxt' if processing a @deriving@ clause.
|
| ... | ... | @@ -563,11 +559,17 @@ data PredSpec |
| 563 | 559 | SimplePredSpec
|
| 564 | 560 | { sps_pred :: TcPredType
|
| 565 | 561 | -- ^ The constraint to emit as a wanted
|
| 562 | + -- Usually just a simple predicate like (Eq a) or (ki ~# Type),
|
|
| 563 | + -- but (hack) in the case of GHC.Tc.Deriv.Infer.inferConstraintsCoerceBased,
|
|
| 564 | + -- it can be a forall-constraint
|
|
| 565 | + |
|
| 566 | 566 | , sps_origin :: CtOrigin
|
| 567 | 567 | -- ^ The origin of the constraint
|
| 568 | + |
|
| 568 | 569 | , sps_type_or_kind :: TypeOrKind
|
| 569 | 570 | -- ^ Whether the constraint is a type or kind
|
| 570 | 571 | }
|
| 572 | + |
|
| 571 | 573 | | -- | A special 'PredSpec' that is only used by @DeriveAnyClass@. This
|
| 572 | 574 | -- will check if @stps_ty_actual@ is a subtype of (i.e., more polymorphic
|
| 573 | 575 | -- than) @stps_ty_expected@ in the constraint solving machinery, emitting an
|
| ... | ... | @@ -677,8 +679,8 @@ captureThetaSpecConstraints :: |
| 677 | 679 | -- @deriving@ declaration
|
| 678 | 680 | -> ThetaSpec -- ^ The specs from which constraints will be created
|
| 679 | 681 | -> TcM (TcLevel, WantedConstraints)
|
| 680 | -captureThetaSpecConstraints user_ctxt theta =
|
|
| 681 | - pushTcLevelM $ mk_wanteds theta
|
|
| 682 | +captureThetaSpecConstraints user_ctxt theta
|
|
| 683 | + = pushTcLevelM $ mk_wanteds theta
|
|
| 682 | 684 | where
|
| 683 | 685 | -- Create the constraints we need to solve. For stock and newtype
|
| 684 | 686 | -- deriving, these constraints will be simple wanted constraints
|
| ... | ... | @@ -689,34 +691,48 @@ captureThetaSpecConstraints user_ctxt theta = |
| 689 | 691 | mk_wanteds :: ThetaSpec -> TcM WantedConstraints
|
| 690 | 692 | mk_wanteds preds
|
| 691 | 693 | = do { (_, wanteds) <- captureConstraints $
|
| 692 | - traverse_ emit_constraints preds
|
|
| 694 | + mapM_ (emitPredSpecConstraints user_ctxt) preds
|
|
| 693 | 695 | ; pure wanteds }
|
| 694 | 696 | |
| 695 | - -- Emit the appropriate constraints depending on what sort of
|
|
| 696 | - -- PredSpec we are dealing with.
|
|
| 697 | - emit_constraints :: PredSpec -> TcM ()
|
|
| 698 | - emit_constraints ps =
|
|
| 699 | - case ps of
|
|
| 700 | - -- For constraints like (C a, Ord b), emit the
|
|
| 701 | - -- constraints directly as simple wanted constraints.
|
|
| 702 | - SimplePredSpec { sps_pred = wanted
|
|
| 703 | - , sps_origin = orig
|
|
| 704 | - , sps_type_or_kind = t_or_k
|
|
| 705 | - } -> do
|
|
| 706 | - ev <- newWanted orig (Just t_or_k) wanted
|
|
| 707 | - emitSimple (mkNonCanonical ev)
|
|
| 708 | - |
|
| 709 | - -- For DeriveAnyClass, check if ty_actual is a subtype of
|
|
| 710 | - -- ty_expected, which emits an implication constraint as a
|
|
| 711 | - -- side effect. See
|
|
| 712 | - -- Note [Gathering and simplifying constraints for DeriveAnyClass].
|
|
| 713 | - -- in GHC.Tc.Deriv.Infer.
|
|
| 714 | - SubTypePredSpec { stps_ty_actual = ty_actual
|
|
| 715 | - , stps_ty_expected = ty_expected
|
|
| 716 | - , stps_origin = orig
|
|
| 717 | - } -> do
|
|
| 718 | - _ <- tcSubTypeSigma orig user_ctxt ty_actual ty_expected
|
|
| 719 | - return ()
|
|
| 697 | +emitPredSpecConstraints :: UserTypeCtxt -> PredSpec -> TcM ()
|
|
| 698 | +--- Emit the appropriate constraints depending on what sort of
|
|
| 699 | +-- PredSpec we are dealing with.
|
|
| 700 | +emitPredSpecConstraints _ (SimplePredSpec { sps_pred = wanted_pred
|
|
| 701 | + , sps_origin = orig
|
|
| 702 | + , sps_type_or_kind = t_or_k })
|
|
| 703 | + -- For constraints like (C a) or (Ord b), emit the
|
|
| 704 | + -- constraints directly as simple wanted constraints.
|
|
| 705 | + | isRhoTy wanted_pred
|
|
| 706 | + = do { ev <- newWanted orig (Just t_or_k) wanted_pred
|
|
| 707 | + ; emitSimple (mkNonCanonical ev) }
|
|
| 708 | + |
|
| 709 | + | otherwise
|
|
| 710 | + -- Forall-constraints, which come exclusively from
|
|
| 711 | + -- GHC.Tc.Deriv.Infer.inferConstraintsCoerceBased.
|
|
| 712 | + -- For these we want to emit an implication constraint, and NOT a forall-constraint
|
|
| 713 | + -- Why? Because forall-constraints are solved all-or-nothing, but here when we
|
|
| 714 | + -- are trying to infer the context for an instance decl, we need that half-solved
|
|
| 715 | + -- implicatation (see deriving/should_compile/T20815).
|
|
| 716 | + = do { let skol_info_anon = DerivSkol wanted_pred
|
|
| 717 | + ; skol_info <- mkSkolemInfo skol_info_anon
|
|
| 718 | + ; (_wrapper, tv_prs, givens, wanted_rho) <- topSkolemise skol_info wanted_pred
|
|
| 719 | + -- _wrapper: we ignore the evidence from all these constraints
|
|
| 720 | + ; (tc_lvl, ev) <- pushTcLevelM $ newWanted orig (Just t_or_k) wanted_rho
|
|
| 721 | + ; let skol_tvs = map (binderVar . snd) tv_prs
|
|
| 722 | + ; (implic, _) <- buildImplicationFor tc_lvl skol_info_anon skol_tvs
|
|
| 723 | + givens (mkSimpleWC [ev])
|
|
| 724 | + ; emitImplications implic }
|
|
| 725 | + |
|
| 726 | +emitPredSpecConstraints user_ctxt
|
|
| 727 | + (SubTypePredSpec { stps_ty_actual = ty_actual
|
|
| 728 | + , stps_ty_expected = ty_expected
|
|
| 729 | + , stps_origin = orig })
|
|
| 730 | +-- For DeriveAnyClass, check if ty_actual is a subtype of ty_expected,
|
|
| 731 | +-- which emits an implication constraint as a side effect. See
|
|
| 732 | +-- Note [Gathering and simplifying constraints for DeriveAnyClass]
|
|
| 733 | +-- in GHC.Tc.Deriv.Infer.
|
|
| 734 | + = do { _ <- tcSubTypeSigma orig user_ctxt ty_actual ty_expected
|
|
| 735 | + ; return () }
|
|
| 720 | 736 | |
| 721 | 737 | {-
|
| 722 | 738 | ************************************************************************
|
| ... | ... | @@ -12,3 +12,5 @@ instance Alt [] where |
| 12 | 12 | (<!>) = (++)
|
| 13 | 13 | |
| 14 | 14 | newtype L a = L [a] deriving (Functor, Alt)
|
| 15 | + |
|
| 16 | +newtype T f a = T (f a) deriving (Functor, Alt) |