Simon Peyton Jones pushed to branch wip/T26003 at Glasgow Haskell Compiler / GHC
Commits:
-
ce616f49
by Simon Peyton Jones at 2025-04-27T21:10:25+01:00
-
22d11fa8
by Simon Peyton Jones at 2025-04-28T18:05:19-04:00
-
4ab20fe4
by Simon Peyton Jones at 2025-04-29T09:36:41+01:00
-
c31925a1
by Simon Peyton Jones at 2025-04-29T10:04:02+01:00
27 changed files:
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Rules.hs
- compiler/GHC/Core/Unify.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Equality.hs
- compiler/GHC/Tc/Solver/InertSet.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Rewrite.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Tc/Zonk/TcType.hs
- compiler/GHC/Tc/Zonk/Type.hs
- compiler/GHC/Types/Basic.hs
- testsuite/tests/indexed-types/should_fail/T3330c.stderr
- testsuite/tests/indexed-types/should_fail/T4174.stderr
- testsuite/tests/indexed-types/should_fail/T8227.stderr
- + testsuite/tests/simplCore/should_compile/T25703.hs
- + testsuite/tests/simplCore/should_compile/T25703.stderr
- + testsuite/tests/simplCore/should_compile/T25703a.hs
- + testsuite/tests/simplCore/should_compile/T25703a.stderr
- + testsuite/tests/simplCore/should_compile/T25965.hs
- testsuite/tests/simplCore/should_compile/all.T
- testsuite/tests/typecheck/should_compile/T25266a.stderr
- testsuite/tests/typecheck/should_fail/T18851.stderr
Changes:
| ... | ... | @@ -120,7 +120,7 @@ module GHC.Core.Coercion ( |
| 120 | 120 | |
| 121 | 121 | multToCo, mkRuntimeRepCo,
|
| 122 | 122 | |
| 123 | - hasCoercionHoleTy, hasCoercionHoleCo, hasThisCoercionHoleTy,
|
|
| 123 | + hasHeteroKindCoercionHoleTy, hasHeteroKindCoercionHoleCo,
|
|
| 124 | 124 | |
| 125 | 125 | setCoHoleType
|
| 126 | 126 | ) where
|
| ... | ... | @@ -2795,24 +2795,12 @@ has_co_hole_co :: Coercion -> Monoid.Any |
| 2795 | 2795 | -- | Is there a hetero-kind coercion hole in this type?
|
| 2796 | 2796 | -- (That is, a coercion hole with ch_hetero_kind=True.)
|
| 2797 | 2797 | -- See wrinkle (EIK2) of Note [Equalities with incompatible kinds] in GHC.Tc.Solver.Equality
|
| 2798 | -hasCoercionHoleTy :: Type -> Bool
|
|
| 2799 | -hasCoercionHoleTy = Monoid.getAny . has_co_hole_ty
|
|
| 2798 | +hasHeteroKindCoercionHoleTy :: Type -> Bool
|
|
| 2799 | +hasHeteroKindCoercionHoleTy = Monoid.getAny . has_co_hole_ty
|
|
| 2800 | 2800 | |
| 2801 | 2801 | -- | Is there a hetero-kind coercion hole in this coercion?
|
| 2802 | -hasCoercionHoleCo :: Coercion -> Bool
|
|
| 2803 | -hasCoercionHoleCo = Monoid.getAny . has_co_hole_co
|
|
| 2804 | - |
|
| 2805 | -hasThisCoercionHoleTy :: Type -> CoercionHole -> Bool
|
|
| 2806 | -hasThisCoercionHoleTy ty hole = Monoid.getAny (f ty)
|
|
| 2807 | - where
|
|
| 2808 | - (f, _, _, _) = foldTyCo folder ()
|
|
| 2809 | - |
|
| 2810 | - folder = TyCoFolder { tcf_view = noView
|
|
| 2811 | - , tcf_tyvar = const2 (Monoid.Any False)
|
|
| 2812 | - , tcf_covar = const2 (Monoid.Any False)
|
|
| 2813 | - , tcf_hole = \ _ h -> Monoid.Any (getUnique h == getUnique hole)
|
|
| 2814 | - , tcf_tycobinder = const2
|
|
| 2815 | - }
|
|
| 2802 | +hasHeteroKindCoercionHoleCo :: Coercion -> Bool
|
|
| 2803 | +hasHeteroKindCoercionHoleCo = Monoid.getAny . has_co_hole_co
|
|
| 2816 | 2804 | |
| 2817 | 2805 | -- | Set the type of a 'CoercionHole'
|
| 2818 | 2806 | setCoHoleType :: CoercionHole -> Type -> CoercionHole
|
| ... | ... | @@ -1243,14 +1243,15 @@ specExpr env (Let bind body) |
| 1243 | 1243 | -- Note [Fire rules in the specialiser]
|
| 1244 | 1244 | fireRewriteRules :: SpecEnv -> InExpr -> [OutExpr] -> (InExpr, [OutExpr])
|
| 1245 | 1245 | fireRewriteRules env (Var f) args
|
| 1246 | - | Just (rule, expr) <- specLookupRule env f args InitialPhase (getRules (se_rules env) f)
|
|
| 1246 | + | let rules = getRules (se_rules env) f
|
|
| 1247 | + , Just (rule, expr) <- specLookupRule env f args activeInInitialPhase rules
|
|
| 1247 | 1248 | , let rest_args = drop (ruleArity rule) args -- See Note [Extra args in the target]
|
| 1248 | 1249 | zapped_subst = Core.zapSubst (se_subst env)
|
| 1249 | 1250 | expr' = simpleOptExprWith defaultSimpleOpts zapped_subst expr
|
| 1250 | 1251 | -- simplOptExpr needed because lookupRule returns
|
| 1251 | 1252 | -- (\x y. rhs) arg1 arg2
|
| 1252 | - , (fun, args) <- collectArgs expr'
|
|
| 1253 | - = fireRewriteRules env fun (args++rest_args)
|
|
| 1253 | + , (fun', args') <- collectArgs expr'
|
|
| 1254 | + = fireRewriteRules env fun' (args'++rest_args)
|
|
| 1254 | 1255 | fireRewriteRules _ fun args = (fun, args)
|
| 1255 | 1256 | |
| 1256 | 1257 | --------------
|
| ... | ... | @@ -1620,7 +1621,7 @@ specCalls :: Bool -- True => specialising imported fn |
| 1620 | 1621 | |
| 1621 | 1622 | -- This function checks existing rules, and does not create
|
| 1622 | 1623 | -- duplicate ones. So the caller does not need to do this filtering.
|
| 1623 | --- See 'already_covered'
|
|
| 1624 | +-- See `alreadyCovered`
|
|
| 1624 | 1625 | |
| 1625 | 1626 | type SpecInfo = ( [CoreRule] -- Specialisation rules
|
| 1626 | 1627 | , [(Id,CoreExpr)] -- Specialised definition
|
| ... | ... | @@ -1644,15 +1645,13 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs |
| 1644 | 1645 | |
| 1645 | 1646 | = -- pprTrace "specCalls: some" (vcat
|
| 1646 | 1647 | -- [ text "function" <+> ppr fn
|
| 1647 | - -- , text "calls:" <+> ppr calls_for_me
|
|
| 1648 | - -- , text "subst" <+> ppr (se_subst env) ]) $
|
|
| 1648 | + -- , text "calls:" <+> ppr calls_for_me
|
|
| 1649 | + -- , text "subst" <+> ppr (se_subst env) ]) $
|
|
| 1649 | 1650 | foldlM spec_call ([], [], emptyUDs) calls_for_me
|
| 1650 | 1651 | |
| 1651 | 1652 | | otherwise -- No calls or RHS doesn't fit our preconceptions
|
| 1652 | - = warnPprTrace (not (exprIsTrivial rhs) && notNull calls_for_me && not (isClassOpId fn))
|
|
| 1653 | + = warnPprTrace (not (exprIsTrivial rhs) && notNull calls_for_me)
|
|
| 1653 | 1654 | "Missed specialisation opportunity for" (ppr fn $$ trace_doc) $
|
| 1654 | - -- isClassOpId: class-op Ids never inline; we specialise them
|
|
| 1655 | - -- through fireRewriteRules. So don't complain about missed opportunities
|
|
| 1656 | 1655 | -- Note [Specialisation shape]
|
| 1657 | 1656 | -- pprTrace "specCalls: none" (ppr fn <+> ppr calls_for_me) $
|
| 1658 | 1657 | return ([], [], emptyUDs)
|
| ... | ... | @@ -1664,6 +1663,10 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs |
| 1664 | 1663 | fn_unf = realIdUnfolding fn -- Ignore loop-breaker-ness here
|
| 1665 | 1664 | inl_prag = idInlinePragma fn
|
| 1666 | 1665 | inl_act = inlinePragmaActivation inl_prag
|
| 1666 | + is_active = isActive (beginPhase inl_act) :: Activation -> Bool
|
|
| 1667 | + -- is_active: inl_act is the activation we are going to put in the new
|
|
| 1668 | + -- SPEC rule; so we want to see if it is covered by another rule with
|
|
| 1669 | + -- that same activation.
|
|
| 1667 | 1670 | is_local = isLocalId fn
|
| 1668 | 1671 | is_dfun = isDFunId fn
|
| 1669 | 1672 | dflags = se_dflags env
|
| ... | ... | @@ -1674,16 +1677,6 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs |
| 1674 | 1677 | (rhs_bndrs, rhs_body) = collectBindersPushingCo rhs
|
| 1675 | 1678 | -- See Note [Account for casts in binding]
|
| 1676 | 1679 | |
| 1677 | - already_covered :: SpecEnv -> [CoreRule] -> [CoreExpr] -> Bool
|
|
| 1678 | - already_covered env new_rules args -- Note [Specialisations already covered]
|
|
| 1679 | - = isJust (specLookupRule env fn args (beginPhase inl_act)
|
|
| 1680 | - (new_rules ++ existing_rules))
|
|
| 1681 | - -- Rules: we look both in the new_rules (generated by this invocation
|
|
| 1682 | - -- of specCalls), and in existing_rules (passed in to specCalls)
|
|
| 1683 | - -- inl_act: is the activation we are going to put in the new SPEC
|
|
| 1684 | - -- rule; so we want to see if it is covered by another rule with
|
|
| 1685 | - -- that same activation.
|
|
| 1686 | - |
|
| 1687 | 1680 | ----------------------------------------------------------
|
| 1688 | 1681 | -- Specialise to one particular call pattern
|
| 1689 | 1682 | spec_call :: SpecInfo -- Accumulating parameter
|
| ... | ... | @@ -1717,8 +1710,12 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs |
| 1717 | 1710 | -- , ppr dx_binds ]) $
|
| 1718 | 1711 | -- return ()
|
| 1719 | 1712 | |
| 1713 | + ; let all_rules = rules_acc ++ existing_rules
|
|
| 1714 | + -- all_rules: we look both in the rules_acc (generated by this invocation
|
|
| 1715 | + -- of specCalls), and in existing_rules (passed in to specCalls)
|
|
| 1720 | 1716 | ; if not useful -- No useful specialisation
|
| 1721 | - || already_covered rhs_env2 rules_acc rule_lhs_args
|
|
| 1717 | + || alreadyCovered rhs_env2 rule_bndrs fn rule_lhs_args is_active all_rules
|
|
| 1718 | + -- See (SC1) in Note [Specialisations already covered]
|
|
| 1722 | 1719 | then return spec_acc
|
| 1723 | 1720 | else
|
| 1724 | 1721 | do { -- Run the specialiser on the specialised RHS
|
| ... | ... | @@ -1780,7 +1777,7 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs |
| 1780 | 1777 | spec_fn_details
|
| 1781 | 1778 | = case idDetails fn of
|
| 1782 | 1779 | JoinId join_arity _ -> JoinId (join_arity - join_arity_decr) Nothing
|
| 1783 | - DFunId is_nt -> DFunId is_nt
|
|
| 1780 | + DFunId unary -> DFunId unary
|
|
| 1784 | 1781 | _ -> VanillaId
|
| 1785 | 1782 | |
| 1786 | 1783 | ; spec_fn <- newSpecIdSM (idName fn) spec_fn_ty spec_fn_details spec_fn_info
|
| ... | ... | @@ -1804,6 +1801,8 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs |
| 1804 | 1801 | , ppr spec_fn <+> dcolon <+> ppr spec_fn_ty
|
| 1805 | 1802 | , ppr rhs_bndrs, ppr call_args
|
| 1806 | 1803 | , ppr spec_rule
|
| 1804 | + , text "acc" <+> ppr rules_acc
|
|
| 1805 | + , text "existing" <+> ppr existing_rules
|
|
| 1807 | 1806 | ]
|
| 1808 | 1807 | |
| 1809 | 1808 | ; -- pprTrace "spec_call: rule" _rule_trace_doc
|
| ... | ... | @@ -1812,19 +1811,35 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs |
| 1812 | 1811 | , spec_uds `thenUDs` uds_acc
|
| 1813 | 1812 | ) } }
|
| 1814 | 1813 | |
| 1814 | +alreadyCovered :: SpecEnv
|
|
| 1815 | + -> [Var] -> Id -> [CoreExpr] -- LHS of possible new rule
|
|
| 1816 | + -> (Activation -> Bool) -- Which rules are active
|
|
| 1817 | + -> [CoreRule] -> Bool
|
|
| 1818 | +-- Note [Specialisations already covered] esp (SC2)
|
|
| 1819 | +alreadyCovered env bndrs fn args is_active rules
|
|
| 1820 | + = case specLookupRule env fn args is_active rules of
|
|
| 1821 | + Nothing -> False
|
|
| 1822 | + Just (rule, _)
|
|
| 1823 | + | isAutoRule rule -> -- Discard identical rules
|
|
| 1824 | + -- We know that (fn args) is an instance of RULE
|
|
| 1825 | + -- Check if RULE is an instance of (fn args)
|
|
| 1826 | + ruleLhsIsMoreSpecific in_scope bndrs args rule
|
|
| 1827 | + | otherwise -> True -- User rules dominate
|
|
| 1828 | + where
|
|
| 1829 | + in_scope = substInScopeSet (se_subst env)
|
|
| 1830 | + |
|
| 1815 | 1831 | -- Convenience function for invoking lookupRule from Specialise
|
| 1816 | 1832 | -- The SpecEnv's InScopeSet should include all the Vars in the [CoreExpr]
|
| 1817 | 1833 | specLookupRule :: SpecEnv -> Id -> [CoreExpr]
|
| 1818 | - -> CompilerPhase -- Look up rules as if we were in this phase
|
|
| 1834 | + -> (Activation -> Bool) -- Which rules are active
|
|
| 1819 | 1835 | -> [CoreRule] -> Maybe (CoreRule, CoreExpr)
|
| 1820 | -specLookupRule env fn args phase rules
|
|
| 1836 | +specLookupRule env fn args is_active rules
|
|
| 1821 | 1837 | = lookupRule ropts in_scope_env is_active fn args rules
|
| 1822 | 1838 | where
|
| 1823 | 1839 | dflags = se_dflags env
|
| 1824 | 1840 | in_scope = substInScopeSet (se_subst env)
|
| 1825 | 1841 | in_scope_env = ISE in_scope (whenActiveUnfoldingFun is_active)
|
| 1826 | 1842 | ropts = initRuleOpts dflags
|
| 1827 | - is_active = isActive phase
|
|
| 1828 | 1843 | |
| 1829 | 1844 | {- Note [Specialising DFuns]
|
| 1830 | 1845 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -2323,21 +2338,24 @@ This plan is implemented in the Rec case of specBindItself. |
| 2323 | 2338 | Note [Specialisations already covered]
|
| 2324 | 2339 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 2325 | 2340 | We obviously don't want to generate two specialisations for the same
|
| 2326 | -argument pattern. There are two wrinkles
|
|
| 2327 | - |
|
| 2328 | -1. We do the already-covered test in specDefn, not when we generate
|
|
| 2329 | -the CallInfo in mkCallUDs. We used to test in the latter place, but
|
|
| 2330 | -we now iterate the specialiser somewhat, and the Id at the call site
|
|
| 2331 | -might therefore not have all the RULES that we can see in specDefn
|
|
| 2332 | - |
|
| 2333 | -2. What about two specialisations where the second is an *instance*
|
|
| 2334 | -of the first? If the more specific one shows up first, we'll generate
|
|
| 2335 | -specialisations for both. If the *less* specific one shows up first,
|
|
| 2336 | -we *don't* currently generate a specialisation for the more specific
|
|
| 2337 | -one. (See the call to lookupRule in already_covered.) Reasons:
|
|
| 2338 | - (a) lookupRule doesn't say which matches are exact (bad reason)
|
|
| 2339 | - (b) if the earlier specialisation is user-provided, it's
|
|
| 2340 | - far from clear that we should auto-specialise further
|
|
| 2341 | +argument pattern. Wrinkles
|
|
| 2342 | + |
|
| 2343 | +(SC1) We do the already-covered test in specDefn, not when we generate
|
|
| 2344 | + the CallInfo in mkCallUDs. We used to test in the latter place, but
|
|
| 2345 | + we now iterate the specialiser somewhat, and the Id at the call site
|
|
| 2346 | + might therefore not have all the RULES that we can see in specDefn
|
|
| 2347 | + |
|
| 2348 | +(SC2) What about two specialisations where the second is an *instance*
|
|
| 2349 | + of the first? It's a bit arbitrary, but here's what we do:
|
|
| 2350 | + * If the existing one is user-specified, via a SPECIALISE pragma, we
|
|
| 2351 | + suppress the further specialisation.
|
|
| 2352 | + * If the existing one is auto-generated, we generate a second RULE
|
|
| 2353 | + for the more specialised version.
|
|
| 2354 | + The latter is important because we don't want the accidental order
|
|
| 2355 | + of calls to determine what specialisations we generate.
|
|
| 2356 | + |
|
| 2357 | +(SC3) Annoyingly, we /also/ eliminate duplicates in `filterCalls`.
|
|
| 2358 | + See (MP3) in Note [Specialising polymorphic dictionaries]
|
|
| 2341 | 2359 | |
| 2342 | 2360 | Note [Auto-specialisation and RULES]
|
| 2343 | 2361 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -2800,12 +2818,10 @@ non-dictionary bindings too. |
| 2800 | 2818 | |
| 2801 | 2819 | Note [Specialising polymorphic dictionaries]
|
| 2802 | 2820 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 2803 | - |
|
| 2804 | 2821 | Note June 2023: This has proved to be quite a tricky optimisation to get right
|
| 2805 | 2822 | see (#23469, #23109, #21229, #23445) so it is now guarded by a flag
|
| 2806 | 2823 | `-fpolymorphic-specialisation`.
|
| 2807 | 2824 | |
| 2808 | - |
|
| 2809 | 2825 | Consider
|
| 2810 | 2826 | class M a where { foo :: a -> Int }
|
| 2811 | 2827 | |
| ... | ... | @@ -2845,11 +2861,26 @@ Here are the moving parts: |
| 2845 | 2861 | function.
|
| 2846 | 2862 | |
| 2847 | 2863 | (MP3) If we have f :: forall m. Monoid m => blah, and two calls
|
| 2848 | - (f @(Endo b) (d :: Monoid (Endo b))
|
|
| 2849 | - (f @(Endo (c->c)) (d :: Monoid (Endo (c->c)))
|
|
| 2864 | + (f @(Endo b) (d1 :: Monoid (Endo b))
|
|
| 2865 | + (f @(Endo (c->c)) (d2 :: Monoid (Endo (c->c)))
|
|
| 2850 | 2866 | we want to generate a specialisation only for the first. The second
|
| 2851 | 2867 | is just a substitution instance of the first, with no greater specialisation.
|
| 2852 | - Hence the call to `remove_dups` in `filterCalls`.
|
|
| 2868 | + Hence the use of `removeDupCalls` in `filterCalls`.
|
|
| 2869 | + |
|
| 2870 | + You might wonder if `d2` might be more specialised than `d1`; but no.
|
|
| 2871 | + This `removeDupCalls` thing is at the definition site of `f`, and both `d1`
|
|
| 2872 | + and `d2` are in scope. So `d1` is simply more polymorphic than `d2`, but
|
|
| 2873 | + is just as specialised.
|
|
| 2874 | + |
|
| 2875 | + This distinction is sadly lost once we build a RULE, so `alreadyCovered`
|
|
| 2876 | + can't be so clever. E.g if we have an existing RULE
|
|
| 2877 | + forall @a (d1:Ord Int) (d2: Eq a). f @a @Int d1 d2 = ...
|
|
| 2878 | + and a putative new rule
|
|
| 2879 | + forall (d1:Ord Int) (d2: Eq Int). f @Int @Int d1 d2 = ...
|
|
| 2880 | + we /don't/ want the existing rule to subsume the new one.
|
|
| 2881 | + |
|
| 2882 | + So we sadly put up with having two rather different places where we
|
|
| 2883 | + eliminate duplicates: `alreadyCovered` and `removeDupCalls`.
|
|
| 2853 | 2884 | |
| 2854 | 2885 | All this arose in #13873, in the unexpected form that a SPECIALISE
|
| 2855 | 2886 | pragma made the program slower! The reason was that the specialised
|
| ... | ... | @@ -2947,16 +2978,29 @@ data CallInfoSet = CIS Id (Bag CallInfo) |
| 2947 | 2978 | -- The list of types and dictionaries is guaranteed to
|
| 2948 | 2979 | -- match the type of f
|
| 2949 | 2980 | -- The Bag may contain duplicate calls (i.e. f @T and another f @T)
|
| 2950 | - -- These dups are eliminated by already_covered in specCalls
|
|
| 2981 | + -- These dups are eliminated by alreadyCovered in specCalls
|
|
| 2951 | 2982 | |
| 2952 | 2983 | data CallInfo
|
| 2953 | - = CI { ci_key :: [SpecArg] -- All arguments
|
|
| 2984 | + = CI { ci_key :: [SpecArg] -- Arguments of the call
|
|
| 2985 | + -- See Note [The (CI-KEY) invariant]
|
|
| 2986 | + |
|
| 2954 | 2987 | , ci_fvs :: IdSet -- Free Ids of the ci_key call
|
| 2955 | 2988 | -- /not/ including the main id itself, of course
|
| 2956 | 2989 | -- NB: excluding tyvars:
|
| 2957 | 2990 | -- See Note [Specialising polymorphic dictionaries]
|
| 2958 | 2991 | }
|
| 2959 | 2992 | |
| 2993 | +{- Note [The (CI-KEY) invariant]
|
|
| 2994 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 2995 | +Invariant (CI-KEY):
|
|
| 2996 | + In the `ci_key :: [SpecArg]` field of `CallInfo`,
|
|
| 2997 | + * The list is non-empty
|
|
| 2998 | + * The least element is always a `SpecDict`
|
|
| 2999 | + |
|
| 3000 | +In this way the RULE has as few args as possible, which broadens its
|
|
| 3001 | +applicability, since rules only fire when saturated.
|
|
| 3002 | +-}
|
|
| 3003 | + |
|
| 2960 | 3004 | type DictExpr = CoreExpr
|
| 2961 | 3005 | |
| 2962 | 3006 | ciSetFilter :: (CallInfo -> Bool) -> CallInfoSet -> CallInfoSet
|
| ... | ... | @@ -3045,10 +3089,7 @@ mkCallUDs' env f args |
| 3045 | 3089 | ci_key :: [SpecArg]
|
| 3046 | 3090 | ci_key = dropWhileEndLE (not . isSpecDict) $
|
| 3047 | 3091 | zipWith mk_spec_arg args pis
|
| 3048 | - -- Drop trailing args until we get to a SpecDict
|
|
| 3049 | - -- In this way the RULE has as few args as possible,
|
|
| 3050 | - -- which broadens its applicability, since rules only
|
|
| 3051 | - -- fire when saturated
|
|
| 3092 | + -- Establish (CI-KEY): drop trailing args until we get to a SpecDict
|
|
| 3052 | 3093 | |
| 3053 | 3094 | mk_spec_arg :: OutExpr -> PiTyBinder -> SpecArg
|
| 3054 | 3095 | mk_spec_arg arg (Named bndr)
|
| ... | ... | @@ -3086,34 +3127,76 @@ site, so we only look through ticks that RULE matching looks through |
| 3086 | 3127 | -}
|
| 3087 | 3128 | |
| 3088 | 3129 | wantCallsFor :: SpecEnv -> Id -> Bool
|
| 3089 | -wantCallsFor _env _f = True
|
|
| 3090 | - -- We could reduce the size of the UsageDetails by being less eager
|
|
| 3091 | - -- about collecting calls for LocalIds: there is no point for
|
|
| 3092 | - -- ones that are lambda-bound. We can't decide this by looking at
|
|
| 3093 | - -- the (absence of an) unfolding, because unfoldings for local
|
|
| 3094 | - -- functions are discarded by cloneBindSM, so no local binder will
|
|
| 3095 | - -- have an unfolding at this stage. We'd have to keep a candidate
|
|
| 3096 | - -- set of let-binders.
|
|
| 3097 | - --
|
|
| 3098 | - -- Not many lambda-bound variables have dictionary arguments, so
|
|
| 3099 | - -- this would make little difference anyway.
|
|
| 3100 | - --
|
|
| 3101 | - -- For imported Ids we could check for an unfolding, but we have to
|
|
| 3102 | - -- do so anyway in canSpecImport, and it seems better to have it
|
|
| 3103 | - -- all in one place. So we simply collect usage info for imported
|
|
| 3104 | - -- overloaded functions.
|
|
| 3105 | - |
|
| 3106 | -{- Note [Interesting dictionary arguments]
|
|
| 3107 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 3108 | -Consider this
|
|
| 3109 | - \a.\d:Eq a. let f = ... in ...(f d)...
|
|
| 3110 | -There really is not much point in specialising f wrt the dictionary d,
|
|
| 3111 | -because the code for the specialised f is not improved at all, because
|
|
| 3112 | -d is lambda-bound. We simply get junk specialisations.
|
|
| 3113 | - |
|
| 3114 | -What is "interesting"? Just that it has *some* structure. But what about
|
|
| 3115 | -variables? We look in the variable's /unfolding/. And that means
|
|
| 3116 | -that we must be careful to ensure that dictionaries have unfoldings,
|
|
| 3130 | +-- See Note [wantCallsFor]
|
|
| 3131 | +wantCallsFor _env f
|
|
| 3132 | + = case idDetails f of
|
|
| 3133 | + RecSelId {} -> False
|
|
| 3134 | + DataConWorkId {} -> False
|
|
| 3135 | + DataConWrapId {} -> False
|
|
| 3136 | + ClassOpId {} -> False
|
|
| 3137 | + PrimOpId {} -> False
|
|
| 3138 | + FCallId {} -> False
|
|
| 3139 | + TickBoxOpId {} -> False
|
|
| 3140 | + CoVarId {} -> False
|
|
| 3141 | + |
|
| 3142 | + DFunId {} -> True
|
|
| 3143 | + VanillaId {} -> True
|
|
| 3144 | + JoinId {} -> True
|
|
| 3145 | + WorkerLikeId {} -> True
|
|
| 3146 | + RepPolyId {} -> True
|
|
| 3147 | + |
|
| 3148 | +{- Note [wantCallsFor]
|
|
| 3149 | +~~~~~~~~~~~~~~~~~~~~~~
|
|
| 3150 | +`wantCallsFor env f` says whether the Specialiser should collect calls for
|
|
| 3151 | +function `f`; other thing being equal, the fewer calls we collect the better. It
|
|
| 3152 | +is False for things we can't specialise:
|
|
| 3153 | + |
|
| 3154 | +* ClassOpId: never inline and we don't have a defn to specialise; we specialise
|
|
| 3155 | + them through fireRewriteRules.
|
|
| 3156 | +* PrimOpId: are never overloaded
|
|
| 3157 | +* Data constructors: we never specialise them
|
|
| 3158 | + |
|
| 3159 | +We could reduce the size of the UsageDetails by being less eager about
|
|
| 3160 | +collecting calls for some LocalIds: there is no point for ones that are
|
|
| 3161 | +lambda-bound. We can't decide this by looking at the (absence of an) unfolding,
|
|
| 3162 | +because unfoldings for local functions are discarded by cloneBindSM, so no local
|
|
| 3163 | +binder will have an unfolding at this stage. We'd have to keep a candidate set
|
|
| 3164 | +of let-binders.
|
|
| 3165 | + |
|
| 3166 | +Not many lambda-bound variables have dictionary arguments, so this would make
|
|
| 3167 | +little difference anyway.
|
|
| 3168 | + |
|
| 3169 | +For imported Ids we could check for an unfolding, but we have to do so anyway in
|
|
| 3170 | +canSpecImport, and it seems better to have it all in one place. So we simply
|
|
| 3171 | +collect usage info for imported overloaded functions.
|
|
| 3172 | + |
|
| 3173 | +Note [Interesting dictionary arguments]
|
|
| 3174 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 3175 | +In `mkCallUDs` we only use `SpecDict` for dictionaries of which
|
|
| 3176 | +`interestingDict` holds. Otherwise we use `UnspecArg`. Two reasons:
|
|
| 3177 | + |
|
| 3178 | +* Consider this
|
|
| 3179 | + \a.\d:Eq a. let f = ... in ...(f d)...
|
|
| 3180 | + There really is not much point in specialising f wrt the dictionary d,
|
|
| 3181 | + because the code for the specialised f is not improved at all, because
|
|
| 3182 | + d is lambda-bound. We simply get junk specialisations.
|
|
| 3183 | + |
|
| 3184 | +* Consider this (#25703):
|
|
| 3185 | + f :: (Eq a, Show b) => a -> b -> INt
|
|
| 3186 | + goo :: forall x. (Eq x) => x -> blah
|
|
| 3187 | + goo @x (d:Eq x) (arg:x) = ...(f @x @Int d $fShowInt)...
|
|
| 3188 | + If we built a `ci_key` with a (SpecDict d) for `d`, we would end up
|
|
| 3189 | + discarding the call at the `\d`. But if we use `UnspecArg` for that
|
|
| 3190 | + uninteresting `d`, we'll get a `ci_key` of
|
|
| 3191 | + f @x @Int UnspecArg (SpecDict $fShowInt)
|
|
| 3192 | + and /that/ can float out to f's definition and specialise nicely.
|
|
| 3193 | + Hooray. (NB: the call can float only if `-fpolymorphic-specialisation`
|
|
| 3194 | + is on; otherwise it'll be trapped by the `\@x -> ...`.)(
|
|
| 3195 | + |
|
| 3196 | +What is "interesting"? (See `interestingDict`.) Just that it has *some*
|
|
| 3197 | +structure. But what about variables? We look in the variable's /unfolding/.
|
|
| 3198 | +And that means that we must be careful to ensure that dictionaries /have/
|
|
| 3199 | +unfoldings,
|
|
| 3117 | 3200 | |
| 3118 | 3201 | * cloneBndrSM discards non-Stable unfoldings
|
| 3119 | 3202 | * specBind updates the unfolding after specialisation
|
| ... | ... | @@ -3159,7 +3242,7 @@ Now `f` turns into: |
| 3159 | 3242 | meth @a dc ....
|
| 3160 | 3243 | |
| 3161 | 3244 | When we specialise `f`, at a=Int say, that superclass selection can
|
| 3162 | -nfire (via rewiteClassOps), but that info (that 'dc' is now a
|
|
| 3245 | +fire (via rewiteClassOps), but that info (that 'dc' is now a
|
|
| 3163 | 3246 | particular dictionary `C`, of type `C Int`) must be available to
|
| 3164 | 3247 | the call `meth @a dc`, so that we can fire the `meth` class-op, and
|
| 3165 | 3248 | thence specialise `wombat`.
|
| ... | ... | @@ -3286,7 +3369,11 @@ dumpUDs :: [CoreBndr] -> UsageDetails -> (UsageDetails, OrdList DictBind) |
| 3286 | 3369 | -- Used at a lambda or case binder; just dump anything mentioning the binder
|
| 3287 | 3370 | dumpUDs bndrs uds@(MkUD { ud_binds = orig_dbs, ud_calls = orig_calls })
|
| 3288 | 3371 | | null bndrs = (uds, nilOL) -- Common in case alternatives
|
| 3289 | - | otherwise = -- pprTrace "dumpUDs" (ppr bndrs $$ ppr free_uds $$ ppr dump_dbs) $
|
|
| 3372 | + | otherwise = -- pprTrace "dumpUDs" (vcat
|
|
| 3373 | + -- [ text "bndrs" <+> ppr bndrs
|
|
| 3374 | + -- , text "uds" <+> ppr uds
|
|
| 3375 | + -- , text "free_uds" <+> ppr free_uds
|
|
| 3376 | + -- , text "dump-dbs" <+> ppr dump_dbs ]) $
|
|
| 3290 | 3377 | (free_uds, dump_dbs)
|
| 3291 | 3378 | where
|
| 3292 | 3379 | free_uds = uds { ud_binds = free_dbs, ud_calls = free_calls }
|
| ... | ... | @@ -3325,20 +3412,17 @@ callsForMe fn uds@MkUD { ud_binds = orig_dbs, ud_calls = orig_calls } |
| 3325 | 3412 | calls_for_me = case lookupDVarEnv orig_calls fn of
|
| 3326 | 3413 | Nothing -> []
|
| 3327 | 3414 | Just cis -> filterCalls cis orig_dbs
|
| 3328 | - -- filterCalls: drop calls that (directly or indirectly)
|
|
| 3329 | - -- refer to fn. See Note [Avoiding loops (DFuns)]
|
|
| 3330 | 3415 | |
| 3331 | 3416 | ----------------------
|
| 3332 | 3417 | filterCalls :: CallInfoSet -> FloatedDictBinds -> [CallInfo]
|
| 3333 | --- Remove dominated calls (Note [Specialising polymorphic dictionaries])
|
|
| 3334 | --- and loopy DFuns (Note [Avoiding loops (DFuns)])
|
|
| 3418 | +-- Remove
|
|
| 3419 | +-- (a) dominated calls: (MP3) in Note [Specialising polymorphic dictionaries]
|
|
| 3420 | +-- (b) loopy DFuns: Note [Avoiding loops (DFuns)]
|
|
| 3335 | 3421 | filterCalls (CIS fn call_bag) (FDB { fdb_binds = dbs })
|
| 3336 | - | isDFunId fn -- Note [Avoiding loops (DFuns)] applies only to DFuns
|
|
| 3337 | - = filter ok_call de_dupd_calls
|
|
| 3338 | - | otherwise -- Do not apply it to non-DFuns
|
|
| 3339 | - = de_dupd_calls -- See Note [Avoiding loops (non-DFuns)]
|
|
| 3422 | + | isDFunId fn = filter ok_call de_dupd_calls -- Deals with (b)
|
|
| 3423 | + | otherwise = de_dupd_calls
|
|
| 3340 | 3424 | where
|
| 3341 | - de_dupd_calls = remove_dups call_bag
|
|
| 3425 | + de_dupd_calls = removeDupCalls call_bag -- Deals with (a)
|
|
| 3342 | 3426 | |
| 3343 | 3427 | dump_set = foldl' go (unitVarSet fn) dbs
|
| 3344 | 3428 | -- This dump-set could also be computed by splitDictBinds
|
| ... | ... | @@ -3352,10 +3436,10 @@ filterCalls (CIS fn call_bag) (FDB { fdb_binds = dbs }) |
| 3352 | 3436 | |
| 3353 | 3437 | ok_call (CI { ci_fvs = fvs }) = fvs `disjointVarSet` dump_set
|
| 3354 | 3438 | |
| 3355 | -remove_dups :: Bag CallInfo -> [CallInfo]
|
|
| 3439 | +removeDupCalls :: Bag CallInfo -> [CallInfo]
|
|
| 3356 | 3440 | -- Calls involving more generic instances beat more specific ones.
|
| 3357 | 3441 | -- See (MP3) in Note [Specialising polymorphic dictionaries]
|
| 3358 | -remove_dups calls = foldr add [] calls
|
|
| 3442 | +removeDupCalls calls = foldr add [] calls
|
|
| 3359 | 3443 | where
|
| 3360 | 3444 | add :: CallInfo -> [CallInfo] -> [CallInfo]
|
| 3361 | 3445 | add ci [] = [ci]
|
| ... | ... | @@ -3364,12 +3448,20 @@ remove_dups calls = foldr add [] calls |
| 3364 | 3448 | | otherwise = ci2 : add ci1 cis
|
| 3365 | 3449 | |
| 3366 | 3450 | beats_or_same :: CallInfo -> CallInfo -> Bool
|
| 3451 | +-- (beats_or_same ci1 ci2) is True if specialising on ci1 subsumes ci2
|
|
| 3452 | +-- That is: ci1's types are less specialised than ci2
|
|
| 3453 | +-- ci1 specialises on the same dict args as ci2
|
|
| 3367 | 3454 | beats_or_same (CI { ci_key = args1 }) (CI { ci_key = args2 })
|
| 3368 | 3455 | = go args1 args2
|
| 3369 | 3456 | where
|
| 3370 | - go [] _ = True
|
|
| 3457 | + go [] [] = True
|
|
| 3371 | 3458 | go (arg1:args1) (arg2:args2) = go_arg arg1 arg2 && go args1 args2
|
| 3372 | - go (_:_) [] = False
|
|
| 3459 | + |
|
| 3460 | + -- If one or the other runs dry, the other must still have a SpecDict
|
|
| 3461 | + -- because of the (CI-KEY) invariant. So neither subsumes the other;
|
|
| 3462 | + -- one is more specialised (faster code) but the other is more generally
|
|
| 3463 | + -- applicable.
|
|
| 3464 | + go _ _ = False
|
|
| 3373 | 3465 | |
| 3374 | 3466 | go_arg (SpecType ty1) (SpecType ty2) = isJust (tcMatchTy ty1 ty2)
|
| 3375 | 3467 | go_arg UnspecType UnspecType = True
|
| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | -- The 'CoreRule' datatype itself is declared elsewhere.
|
| 10 | 10 | module GHC.Core.Rules (
|
| 11 | 11 | -- ** Looking up rules
|
| 12 | - lookupRule, matchExprs,
|
|
| 12 | + lookupRule, matchExprs, ruleLhsIsMoreSpecific,
|
|
| 13 | 13 | |
| 14 | 14 | -- ** RuleBase, RuleEnv
|
| 15 | 15 | RuleBase, RuleEnv(..), mkRuleEnv, emptyRuleEnv,
|
| ... | ... | @@ -587,8 +587,8 @@ findBest :: InScopeSet -> (Id, [CoreExpr]) |
| 587 | 587 | |
| 588 | 588 | findBest _ _ (rule,ans) [] = (rule,ans)
|
| 589 | 589 | findBest in_scope target (rule1,ans1) ((rule2,ans2):prs)
|
| 590 | - | isMoreSpecific in_scope rule1 rule2 = findBest in_scope target (rule1,ans1) prs
|
|
| 591 | - | isMoreSpecific in_scope rule2 rule1 = findBest in_scope target (rule2,ans2) prs
|
|
| 590 | + | ruleIsMoreSpecific in_scope rule1 rule2 = findBest in_scope target (rule1,ans1) prs
|
|
| 591 | + | ruleIsMoreSpecific in_scope rule2 rule1 = findBest in_scope target (rule2,ans2) prs
|
|
| 592 | 592 | | debugIsOn = let pp_rule rule
|
| 593 | 593 | = ifPprDebug (ppr rule)
|
| 594 | 594 | (doubleQuotes (ftext (ruleName rule)))
|
| ... | ... | @@ -603,15 +603,25 @@ findBest in_scope target (rule1,ans1) ((rule2,ans2):prs) |
| 603 | 603 | where
|
| 604 | 604 | (fn,args) = target
|
| 605 | 605 | |
| 606 | -isMoreSpecific :: InScopeSet -> CoreRule -> CoreRule -> Bool
|
|
| 607 | --- The call (rule1 `isMoreSpecific` rule2)
|
|
| 606 | +ruleIsMoreSpecific :: InScopeSet -> CoreRule -> CoreRule -> Bool
|
|
| 607 | +-- The call (rule1 `ruleIsMoreSpecific` rule2)
|
|
| 608 | 608 | -- sees if rule2 can be instantiated to look like rule1
|
| 609 | --- See Note [isMoreSpecific]
|
|
| 610 | -isMoreSpecific _ (BuiltinRule {}) _ = False
|
|
| 611 | -isMoreSpecific _ (Rule {}) (BuiltinRule {}) = True
|
|
| 612 | -isMoreSpecific in_scope (Rule { ru_bndrs = bndrs1, ru_args = args1 })
|
|
| 613 | - (Rule { ru_bndrs = bndrs2, ru_args = args2 })
|
|
| 614 | - = isJust (matchExprs in_scope_env bndrs2 args2 args1)
|
|
| 609 | +-- See Note [ruleIsMoreSpecific]
|
|
| 610 | +ruleIsMoreSpecific in_scope rule1 rule2
|
|
| 611 | + = case rule1 of
|
|
| 612 | + BuiltinRule {} -> False
|
|
| 613 | + Rule { ru_bndrs = bndrs1, ru_args = args1 }
|
|
| 614 | + -> ruleLhsIsMoreSpecific in_scope bndrs1 args1 rule2
|
|
| 615 | + |
|
| 616 | +ruleLhsIsMoreSpecific :: InScopeSet
|
|
| 617 | + -> [Var] -> [CoreExpr] -- LHS of a possible new rule
|
|
| 618 | + -> CoreRule -- An existing rule
|
|
| 619 | + -> Bool -- New one is more specific
|
|
| 620 | +ruleLhsIsMoreSpecific in_scope bndrs1 args1 rule2
|
|
| 621 | + = case rule2 of
|
|
| 622 | + BuiltinRule {} -> True
|
|
| 623 | + Rule { ru_bndrs = bndrs2, ru_args = args2 }
|
|
| 624 | + -> isJust (matchExprs in_scope_env bndrs2 args2 args1)
|
|
| 615 | 625 | where
|
| 616 | 626 | full_in_scope = in_scope `extendInScopeSetList` bndrs1
|
| 617 | 627 | in_scope_env = ISE full_in_scope noUnfoldingFun
|
| ... | ... | @@ -620,9 +630,9 @@ isMoreSpecific in_scope (Rule { ru_bndrs = bndrs1, ru_args = args1 }) |
| 620 | 630 | noBlackList :: Activation -> Bool
|
| 621 | 631 | noBlackList _ = False -- Nothing is black listed
|
| 622 | 632 | |
| 623 | -{- Note [isMoreSpecific]
|
|
| 633 | +{- Note [ruleIsMoreSpecific]
|
|
| 624 | 634 | ~~~~~~~~~~~~~~~~~~~~~~~~
|
| 625 | -The call (rule1 `isMoreSpecific` rule2)
|
|
| 635 | +The call (rule1 `ruleIsMoreSpecific` rule2)
|
|
| 626 | 636 | sees if rule2 can be instantiated to look like rule1.
|
| 627 | 637 | |
| 628 | 638 | Wrinkle:
|
| ... | ... | @@ -825,7 +835,7 @@ bound on the LHS: |
| 825 | 835 | |
| 826 | 836 | The rule looks like
|
| 827 | 837 | forall (a::*) (d::Eq Char) (x :: Foo a Char).
|
| 828 | - f (Foo a Char) d x = True
|
|
| 838 | + f @(Foo a Char) d x = True
|
|
| 829 | 839 | |
| 830 | 840 | Matching the rule won't bind 'a', and legitimately so. We fudge by
|
| 831 | 841 | pretending that 'a' is bound to (Any :: *).
|
| ... | ... | @@ -331,35 +331,57 @@ Wrinkles |
| 331 | 331 | `DontBindMe`, the unifier must return `SurelyApart`, not `MaybeApart`. See
|
| 332 | 332 | `go_fam` in `uVarOrFam`
|
| 333 | 333 | |
| 334 | -(ATF6) You might think that when /matching/ the um_fam_env will always be empty,
|
|
| 335 | - because type-class-instance and type-family-instance heads can't include type
|
|
| 336 | - families. E.g. instance C (F a) where ... -- Illegal
|
|
| 337 | - |
|
| 338 | - But you'd be wrong: when "improving" type family constraint we may have a
|
|
| 339 | - type family on the LHS of a match. Consider
|
|
| 334 | +(ATF6) When /matching/ can we ever have a type-family application on the LHS, in
|
|
| 335 | + the template? You might think not, because type-class-instance and
|
|
| 336 | + type-family-instance heads can't include type families. E.g.
|
|
| 337 | + instance C (F a) where ... -- Illegal
|
|
| 338 | + |
|
| 339 | + But you'd be wrong: even when matching, we can see type families in the LHS template:
|
|
| 340 | + * In `checkValidClass`, in `check_dm` we check that the default method has the
|
|
| 341 | + right type, using matching, both ways. And that type may have type-family
|
|
| 342 | + applications in it. Example in test CoOpt_Singletons.
|
|
| 343 | + |
|
| 344 | + * In the specialiser: see the call to `tcMatchTy` in
|
|
| 345 | + `GHC.Core.Opt.Specialise.beats_or_same`
|
|
| 346 | + |
|
| 347 | + * With -fpolymorphic-specialsation, we might get a specialiation rule like
|
|
| 348 | + RULE forall a (d :: Eq (Maybe (F a))) .
|
|
| 349 | + f @(Maybe (F a)) d = ...
|
|
| 350 | + See #25965.
|
|
| 351 | + |
|
| 352 | + * A user-written RULE could conceivably have a type-family application
|
|
| 353 | + in the template. It might not be a good rule, but I don't think we currently
|
|
| 354 | + check for this.
|
|
| 355 | + |
|
| 356 | + In all these cases we are only interested in finding a substitution /for
|
|
| 357 | + type variables/ that makes the match work. So we simply want to recurse into
|
|
| 358 | + the arguments of the type family. E.g.
|
|
| 359 | + Template: forall a. Maybe (F a)
|
|
| 360 | + Target: Mabybe (F Int)
|
|
| 361 | + We want to succeed with substitution [a :-> Int]. See (ATF9).
|
|
| 362 | + |
|
| 363 | + Conclusion: where we enter via `tcMatchTy`, `tcMatchTys`, `tc_match_tys`,
|
|
| 364 | + etc, we always end up in `tc_match_tys_x`. There we invoke the unifier
|
|
| 365 | + but we do not distinguish between `SurelyApart` and `MaybeApart`. So in
|
|
| 366 | + these cases we can set `um_bind_fam_fun` to `neverBindFam`.
|
|
| 367 | + |
|
| 368 | +(ATF7) There is one other, very special case of matching where we /do/ want to
|
|
| 369 | + bind type families in `um_fam_env`, namely in GHC.Tc.Solver.Equality, the call
|
|
| 370 | + to `tcUnifyTyForInjectivity False` in `improve_injective_wanted_top`.
|
|
| 371 | + Consider
|
|
| 372 | + of a match. Consider
|
|
| 340 | 373 | type family G6 a = r | r -> a
|
| 341 | 374 | type instance G6 [a] = [G a]
|
| 342 | 375 | type instance G6 Bool = Int
|
| 343 | - and the Wanted constraint [W] G6 alpha ~ [Int]. We /match/ each type instance
|
|
| 344 | - RHS against [Int]! So we try
|
|
| 345 | - [G a] ~ [Int]
|
|
| 376 | + and suppose we haev a Wanted constraint
|
|
| 377 | + [W] G6 alpha ~ [Int]
|
|
| 378 | +. According to Section 5.2 of "Injective type families for Haskell", we /match/
|
|
| 379 | + the RHS each type instance [Int]. So we try
|
|
| 380 | + Template: [G a] Target: [Int]
|
|
| 346 | 381 | and we want to succeed with MaybeApart, so that we can generate the improvement
|
| 347 | - constraint [W] alpha ~ [beta] where beta is fresh.
|
|
| 348 | - See Section 5.2 of "Injective type families for Haskell".
|
|
| 349 | - |
|
| 350 | - A second place that we match with type-fams on the LHS is in `checkValidClass`.
|
|
| 351 | - In `check_dm` we check that the default method has the right type, using matching,
|
|
| 352 | - both ways. And that type may have type-family applications in it. Example in
|
|
| 353 | - test CoOpt_Singletons.
|
|
| 354 | - |
|
| 355 | -(ATF7) You might think that (ATF6) is a very special case, and in /other/ uses of
|
|
| 356 | - matching, where we enter via `tc_match_tys_x` we will never see a type-family
|
|
| 357 | - in the template. But actually we do see that case in the specialiser: see
|
|
| 358 | - the call to `tcMatchTy` in `GHC.Core.Opt.Specialise.beats_or_same`
|
|
| 359 | - |
|
| 360 | - Also: a user-written RULE could conceivably have a type-family application
|
|
| 361 | - in the template. It might not be a good rule, but I don't think we currently
|
|
| 362 | - check for this.
|
|
| 382 | + constraint
|
|
| 383 | + [W] alpha ~ [beta]
|
|
| 384 | + where beta is fresh. We do this by binding [G a :-> Int]
|
|
| 363 | 385 | |
| 364 | 386 | (ATF8) The treatment of type families is governed by
|
| 365 | 387 | um_bind_fam_fun :: BindFamFun
|
| ... | ... | @@ -399,6 +421,8 @@ Wrinkles |
| 399 | 421 | Key point: when decomposing (F tys1 ~ F tys2), we should /also/ extend the
|
| 400 | 422 | type-family substitution.
|
| 401 | 423 | |
| 424 | + (ATF11-1) All this cleverness only matters when unifying, not when matching
|
|
| 425 | + |
|
| 402 | 426 | (ATF12) There is a horrid exception for the injectivity check. See (UR1) in
|
| 403 | 427 | in Note [Specification of unification].
|
| 404 | 428 | |
| ... | ... | @@ -595,7 +619,7 @@ tc_match_tys_x :: HasDebugCallStack |
| 595 | 619 | -> [Type]
|
| 596 | 620 | -> Maybe Subst
|
| 597 | 621 | tc_match_tys_x bind_tv match_kis (Subst in_scope id_env tv_env cv_env) tys1 tys2
|
| 598 | - = case tc_unify_tys alwaysBindFam -- (ATF7) in Note [Apartness and type families]
|
|
| 622 | + = case tc_unify_tys neverBindFam -- (ATF7) in Note [Apartness and type families]
|
|
| 599 | 623 | bind_tv
|
| 600 | 624 | False -- Matching, not unifying
|
| 601 | 625 | False -- Not an injectivity check
|
| ... | ... | @@ -1857,6 +1881,7 @@ uVarOrFam env ty1 ty2 kco |
| 1857 | 1881 | = go_fam_fam tc1 tys1 tys2 kco
|
| 1858 | 1882 | |
| 1859 | 1883 | -- Now check if we can bind the (F tys) to the RHS
|
| 1884 | + -- This can happen even when matching: see (ATF7)
|
|
| 1860 | 1885 | | BindMe <- um_bind_fam_fun env tc1 tys1 rhs
|
| 1861 | 1886 | = -- ToDo: do we need an occurs check here?
|
| 1862 | 1887 | do { extendFamEnv tc1 tys1 rhs
|
| ... | ... | @@ -1881,11 +1906,6 @@ uVarOrFam env ty1 ty2 kco |
| 1881 | 1906 | -- go_fam_fam: LHS and RHS are both saturated type-family applications,
|
| 1882 | 1907 | -- for the same type-family F
|
| 1883 | 1908 | go_fam_fam tc tys1 tys2 kco
|
| 1884 | - | tcEqTyConAppArgs tys1 tys2
|
|
| 1885 | - -- Detect (F tys ~ F tys); otherwise we'd build an infinite substitution
|
|
| 1886 | - = return ()
|
|
| 1887 | - |
|
| 1888 | - | otherwise
|
|
| 1889 | 1909 | -- Decompose (F tys1 ~ F tys2): (ATF9)
|
| 1890 | 1910 | -- Use injectivity information of F: (ATF10)
|
| 1891 | 1911 | -- But first bind the type-fam if poss: (ATF11)
|
| ... | ... | @@ -1902,13 +1922,19 @@ uVarOrFam env ty1 ty2 kco |
| 1902 | 1922 | (inj_tys1, noninj_tys1) = partitionByList inj tys1
|
| 1903 | 1923 | (inj_tys2, noninj_tys2) = partitionByList inj tys2
|
| 1904 | 1924 | |
| 1905 | - bind_fam_if_poss | BindMe <- um_bind_fam_fun env tc tys1 rhs1
|
|
| 1906 | - = extendFamEnv tc tys1 rhs1
|
|
| 1907 | - | um_unif env
|
|
| 1908 | - , BindMe <- um_bind_fam_fun env tc tys2 rhs2
|
|
| 1909 | - = extendFamEnv tc tys2 rhs2
|
|
| 1910 | - | otherwise
|
|
| 1911 | - = return ()
|
|
| 1925 | + bind_fam_if_poss
|
|
| 1926 | + | not (um_unif env) -- Not when matching (ATF11-1)
|
|
| 1927 | + = return ()
|
|
| 1928 | + | tcEqTyConAppArgs tys1 tys2 -- Detect (F tys ~ F tys);
|
|
| 1929 | + = return () -- otherwise we'd build an infinite substitution
|
|
| 1930 | + | BindMe <- um_bind_fam_fun env tc tys1 rhs1
|
|
| 1931 | + = extendFamEnv tc tys1 rhs1
|
|
| 1932 | + | um_unif env
|
|
| 1933 | + , BindMe <- um_bind_fam_fun env tc tys2 rhs2
|
|
| 1934 | + = extendFamEnv tc tys2 rhs2
|
|
| 1935 | + | otherwise
|
|
| 1936 | + = return ()
|
|
| 1937 | + |
|
| 1912 | 1938 | rhs1 = mkTyConApp tc tys2 `mkCastTy` mkSymCo kco
|
| 1913 | 1939 | rhs2 = mkTyConApp tc tys1 `mkCastTy` kco
|
| 1914 | 1940 | |
| ... | ... | @@ -1993,7 +2019,7 @@ data UMState = UMState |
| 1993 | 2019 | -- in um_foralls; i.e. variables bound by foralls inside the types being unified
|
| 1994 | 2020 | |
| 1995 | 2021 | -- When /matching/ um_fam_env is usually empty; but not quite always.
|
| 1996 | - -- See (ATF6) and (ATF7) of Note [Apartness and type families]
|
|
| 2022 | + -- See (ATF7) of Note [Apartness and type families]
|
|
| 1997 | 2023 | |
| 1998 | 2024 | newtype UM a
|
| 1999 | 2025 | = UM' { unUM :: UMState -> UnifyResultM (UMState, a) }
|
| ... | ... | @@ -466,13 +466,12 @@ mkErrorItem ct |
| 466 | 466 | = do { let loc = ctLoc ct
|
| 467 | 467 | flav = ctFlavour ct
|
| 468 | 468 | |
| 469 | - ; (suppress, m_evdest) <- case ctEvidence ct of
|
|
| 470 | - -- For this `suppress` stuff
|
|
| 471 | - -- see Note [Wanteds rewrite Wanteds] in GHC.Tc.Types.Constraint
|
|
| 472 | - CtGiven {} -> return (False, Nothing)
|
|
| 473 | - CtWanted (WantedCt { ctev_rewriters = rewriters, ctev_dest = dest })
|
|
| 474 | - -> do { rewriters' <- zonkRewriterSet rewriters
|
|
| 475 | - ; return (not (isEmptyRewriterSet rewriters'), Just dest) }
|
|
| 469 | + (suppress, m_evdest) = case ctEvidence ct of
|
|
| 470 | + -- For this `suppress` stuff
|
|
| 471 | + -- see Note [Wanteds rewrite Wanteds] in GHC.Tc.Types.Constraint
|
|
| 472 | + CtGiven {} -> (False, Nothing)
|
|
| 473 | + CtWanted (WantedCt { ctev_rewriters = rws, ctev_dest = dest })
|
|
| 474 | + -> (not (isEmptyRewriterSet rws), Just dest)
|
|
| 476 | 475 | |
| 477 | 476 | ; let m_reason = case ct of
|
| 478 | 477 | CIrredCan (IrredCt { ir_reason = reason }) -> Just reason
|
| ... | ... | @@ -503,7 +502,7 @@ reportWanteds ctxt tc_lvl wc@(WC { wc_simple = simples, wc_impl = implics |
| 503 | 502 | , text "tidy_errs =" <+> ppr tidy_errs ])
|
| 504 | 503 | |
| 505 | 504 | -- Catch an awkward (and probably rare) case in which /all/ errors are
|
| 506 | - -- suppressed: see Wrinkle (WRW2) in Note [Prioritise Wanteds with empty
|
|
| 505 | + -- suppressed: see Wrinkle (PER2) in Note [Prioritise Wanteds with empty
|
|
| 507 | 506 | -- RewriterSet] in GHC.Tc.Types.Constraint.
|
| 508 | 507 | --
|
| 509 | 508 | -- Unless we are sure that an error will be reported some other way
|
| ... | ... | @@ -1788,7 +1787,8 @@ mkTyVarEqErr ctxt item casted_tv1 ty2 |
| 1788 | 1787 | |
| 1789 | 1788 | mkTyVarEqErr' :: SolverReportErrCtxt -> ErrorItem
|
| 1790 | 1789 | -> (TcTyVar, TcCoercionN) -> TcType -> TcM TcSolverReportMsg
|
| 1791 | -mkTyVarEqErr' ctxt item (tv1, co1) ty2
|
|
| 1790 | +mkTyVarEqErr' ctxt item (tv1, _co1) ty2
|
|
| 1791 | + -- ToDo: eliminate _co1???
|
|
| 1792 | 1792 | |
| 1793 | 1793 | -- Is this a representation-polymorphism error, e.g.
|
| 1794 | 1794 | -- alpha[conc] ~# rr[sk] ? If so, handle that first.
|
| ... | ... | @@ -1818,11 +1818,13 @@ mkTyVarEqErr' ctxt item (tv1, co1) ty2 |
| 1818 | 1818 | -- to be helpful since this is just an unimplemented feature.
|
| 1819 | 1819 | return main_msg
|
| 1820 | 1820 | |
| 1821 | +{-
|
|
| 1821 | 1822 | -- Incompatible kinds
|
| 1822 | 1823 | -- This is wrinkle (EIK2) in Note [Equalities with incompatible kinds]
|
| 1823 | 1824 | -- in GHC.Tc.Solver.Equality
|
| 1824 | - | hasCoercionHoleCo co1 || hasCoercionHoleTy ty2
|
|
| 1825 | + | hasHeteroKindCoercionHoleCo co1 || hasHeteroKindCoercionHoleTy ty2
|
|
| 1825 | 1826 | = return $ mkBlockedEqErr item
|
| 1827 | +-}
|
|
| 1826 | 1828 | |
| 1827 | 1829 | | isSkolemTyVar tv1 -- ty2 won't be a meta-tyvar; we would have
|
| 1828 | 1830 | -- swapped in Solver.Equality.canEqTyVarHomo
|
| ... | ... | @@ -2007,6 +2009,7 @@ misMatchOrCND ctxt item ty1 ty2 |
| 2007 | 2009 | -- Keep only UserGivens that have some equalities.
|
| 2008 | 2010 | -- See Note [Suppress redundant givens during error reporting]
|
| 2009 | 2011 | |
| 2012 | +{-
|
|
| 2010 | 2013 | -- These are for the "blocked" equalities, as described in GHC.Tc.Solver.Equality
|
| 2011 | 2014 | -- Note [Equalities with incompatible kinds], wrinkle (EIK2). There should
|
| 2012 | 2015 | -- always be another unsolved wanted around, which will ordinarily suppress
|
| ... | ... | @@ -2014,6 +2017,7 @@ misMatchOrCND ctxt item ty1 ty2 |
| 2014 | 2017 | -- (sigh), so we must produce a message.
|
| 2015 | 2018 | mkBlockedEqErr :: ErrorItem -> TcSolverReportMsg
|
| 2016 | 2019 | mkBlockedEqErr item = BlockedEquality item
|
| 2020 | +-}
|
|
| 2017 | 2021 | |
| 2018 | 2022 | {-
|
| 2019 | 2023 | Note [Suppress redundant givens during error reporting]
|
| ... | ... | @@ -1081,9 +1081,9 @@ disambigProposalSequences orig_wanteds wanteds proposalSequences allConsistent |
| 1081 | 1081 | ; successes <- fmap catMaybes $
|
| 1082 | 1082 | nestImplicTcS fake_ev_binds_var (pushTcLevel tclvl) $
|
| 1083 | 1083 | mapM firstSuccess proposalSequences
|
| 1084 | - ; traceTcS "disambigProposalSequences" (vcat [ ppr wanteds
|
|
| 1085 | - , ppr proposalSequences
|
|
| 1086 | - , ppr successes ])
|
|
| 1084 | + ; traceTcS "disambigProposalSequences {" (vcat [ ppr wanteds
|
|
| 1085 | + , ppr proposalSequences
|
|
| 1086 | + , ppr successes ])
|
|
| 1087 | 1087 | -- Step (4) in Note [How type-class constraints are defaulted]
|
| 1088 | 1088 | ; case successes of
|
| 1089 | 1089 | success@(tvs, subst) : rest
|
| ... | ... | @@ -1613,54 +1613,59 @@ canEqCanLHSHetero ev eq_rel swapped lhs1 ps_xi1 ki1 xi2 ps_xi2 ki2 |
| 1613 | 1613 | -- NotSwapped:
|
| 1614 | 1614 | -- ev :: (lhs1:ki1) ~r# (xi2:ki2)
|
| 1615 | 1615 | -- kind_co :: k11 ~# ki2 -- Same orientation as ev
|
| 1616 | --- type_ev :: lhs1 ~r# (xi2 |> sym kind_co)
|
|
| 1616 | +-- new_ev :: lhs1 ~r# (xi2 |> sym kind_co)
|
|
| 1617 | 1617 | -- Swapped
|
| 1618 | 1618 | -- ev :: (xi2:ki2) ~r# (lhs1:ki1)
|
| 1619 | 1619 | -- kind_co :: ki2 ~# ki1 -- Same orientation as ev
|
| 1620 | --- type_ev :: (xi2 |> kind_co) ~r# lhs1
|
|
| 1620 | +-- new_ev :: (xi2 |> kind_co) ~r# lhs1
|
|
| 1621 | +-- Note that we need the `sym` when we are /not/ swapped; hence `mk_sym_co`
|
|
| 1621 | 1622 | |
| 1622 | - = do { (kind_co, rewriters, unifs_happened) <- mk_kind_eq -- :: ki1 ~N ki2
|
|
| 1623 | - ; if unifs_happened
|
|
| 1624 | - -- Unifications happened, so start again to do the zonking
|
|
| 1625 | - -- Otherwise we might put something in the inert set that isn't inert
|
|
| 1626 | - then startAgainWith (mkNonCanonical ev)
|
|
| 1627 | - else
|
|
| 1628 | - do { let lhs_redn = mkReflRedn role ps_xi1
|
|
| 1629 | - rhs_redn = mkGReflRightRedn role xi2 mb_sym_kind_co
|
|
| 1630 | - mb_sym_kind_co = case swapped of
|
|
| 1631 | - NotSwapped -> mkSymCo kind_co
|
|
| 1632 | - IsSwapped -> kind_co
|
|
| 1633 | - |
|
| 1634 | - ; traceTcS "Hetero equality gives rise to kind equality"
|
|
| 1635 | - (ppr swapped $$
|
|
| 1636 | - ppr kind_co <+> dcolon <+> sep [ ppr ki1, text "~#", ppr ki2 ])
|
|
| 1637 | - ; type_ev <- rewriteEqEvidence rewriters ev swapped lhs_redn rhs_redn
|
|
| 1638 | - |
|
| 1639 | - ; let new_xi2 = mkCastTy ps_xi2 mb_sym_kind_co
|
|
| 1640 | - ; canEqCanLHSHomo type_ev eq_rel NotSwapped lhs1 ps_xi1 new_xi2 new_xi2 }}
|
|
| 1641 | - |
|
| 1642 | - where
|
|
| 1643 | - mk_kind_eq :: TcS (CoercionN, RewriterSet, Bool)
|
|
| 1644 | - -- Returned kind_co has kind (k1 ~ k2) if NotSwapped, (k2 ~ k1) if Swapped
|
|
| 1645 | - -- Returned Bool = True if unifications happened, so we should retry
|
|
| 1646 | - mk_kind_eq = case ev of
|
|
| 1623 | + = case ev of
|
|
| 1647 | 1624 | CtGiven (GivenCt { ctev_evar = evar, ctev_loc = loc })
|
| 1648 | 1625 | -> do { let kind_co = mkKindCo (mkCoVarCo evar)
|
| 1649 | 1626 | pred_ty = unSwap swapped mkNomEqPred ki1 ki2
|
| 1650 | 1627 | kind_loc = mkKindEqLoc xi1 xi2 loc
|
| 1651 | 1628 | ; kind_ev <- newGivenEvVar kind_loc (pred_ty, evCoercion kind_co)
|
| 1652 | 1629 | ; emitWorkNC [CtGiven kind_ev]
|
| 1653 | - ; return (givenCtEvCoercion kind_ev, emptyRewriterSet, False) }
|
|
| 1630 | + ; finish emptyRewriterSet (givenCtEvCoercion kind_ev) }
|
|
| 1654 | 1631 | |
| 1655 | 1632 | CtWanted {}
|
| 1656 | - -> do { (kind_co, cts, unifs) <- wrapUnifierTcS ev Nominal $ \uenv ->
|
|
| 1657 | - let uenv' = updUEnvLoc uenv (mkKindEqLoc xi1 xi2)
|
|
| 1658 | - in unSwap swapped (uType uenv') ki1 ki2
|
|
| 1659 | - ; return (kind_co, rewriterSetFromCts cts, not (null unifs)) }
|
|
| 1660 | - |
|
| 1633 | + -> do { (kind_co, cts, unifs) <- wrapUnifierTcS ev Nominal $ \uenv ->
|
|
| 1634 | + let uenv' = updUEnvLoc uenv (mkKindEqLoc xi1 xi2)
|
|
| 1635 | + in unSwap swapped (uType uenv') ki1 ki2
|
|
| 1636 | + ; if not (null unifs)
|
|
| 1637 | + then -- Unifications happened, so start again to do the zonking
|
|
| 1638 | + -- Otherwise we might put something in the inert set that isn't inert
|
|
| 1639 | + startAgainWith (mkNonCanonical ev)
|
|
| 1640 | + else
|
|
| 1641 | + |
|
| 1642 | + assertPpr (not (isEmptyCts cts)) (ppr ev $$ ppr ki1 $$ ppr ki2) $
|
|
| 1643 | + -- The constraints won't be empty because the two kinds differ, and there
|
|
| 1644 | + -- are no unifications, so we must have emitted one or more constraints
|
|
| 1645 | + finish (rewriterSetFromCts cts) kind_co }
|
|
| 1646 | + where
|
|
| 1661 | 1647 | xi1 = canEqLHSType lhs1
|
| 1662 | 1648 | role = eqRelRole eq_rel
|
| 1663 | 1649 | |
| 1650 | + finish rewriters kind_co
|
|
| 1651 | + = do { traceTcS "Hetero equality gives rise to kind equality"
|
|
| 1652 | + (ppr swapped $$
|
|
| 1653 | + ppr kind_co <+> dcolon <+> sep [ ppr ki1, text "~#", ppr ki2 ])
|
|
| 1654 | + ; new_ev <- rewriteEqEvidence rewriters ev swapped lhs_redn rhs_redn
|
|
| 1655 | + ; canEqCanLHSHomo new_ev eq_rel NotSwapped lhs1 ps_xi1 new_xi2 new_xi2 }
|
|
| 1656 | + |
|
| 1657 | + where
|
|
| 1658 | + -- kind_co :: ki1 ~N ki2
|
|
| 1659 | + lhs_redn = mkReflRedn role ps_xi1
|
|
| 1660 | + rhs_redn = mkGReflRightRedn role xi2 sym_kind_co
|
|
| 1661 | + new_xi2 = mkCastTy ps_xi2 sym_kind_co
|
|
| 1662 | + |
|
| 1663 | + -- Apply mkSymCo when /not/ swapped
|
|
| 1664 | + sym_kind_co = case swapped of
|
|
| 1665 | + NotSwapped -> mkSymCo kind_co
|
|
| 1666 | + IsSwapped -> kind_co
|
|
| 1667 | + |
|
| 1668 | + |
|
| 1664 | 1669 | canEqCanLHSHomo :: CtEvidence -- lhs ~ rhs
|
| 1665 | 1670 | -- or, if swapped: rhs ~ lhs
|
| 1666 | 1671 | -> EqRel -> SwapFlag
|
| ... | ... | @@ -1863,9 +1868,10 @@ canEqCanLHSFinish ev eq_rel swapped lhs rhs |
| 1863 | 1868 | -----------------------
|
| 1864 | 1869 | canEqCanLHSFinish_try_unification ev eq_rel swapped lhs rhs
|
| 1865 | 1870 | -- Try unification; for Wanted, Nominal equalities with a meta-tyvar on the LHS
|
| 1866 | - | isWanted ev -- See Note [Do not unify Givens]
|
|
| 1867 | - , NomEq <- eq_rel -- See Note [Do not unify representational equalities]
|
|
| 1871 | + | CtWanted wev <- ev -- See Note [Do not unify Givens]
|
|
| 1872 | + , NomEq <- eq_rel -- See Note [Do not unify representational equalities]
|
|
| 1868 | 1873 | , TyVarLHS tv <- lhs
|
| 1874 | + , isEmptyRewriterSet (ctev_rewriters wev) -- Only unify if the rewriter set is empty
|
|
| 1869 | 1875 | = do { given_eq_lvl <- getInnermostGivenEqLevel
|
| 1870 | 1876 | ; if not (touchabilityAndShapeTest given_eq_lvl tv rhs)
|
| 1871 | 1877 | then if | Just can_rhs <- canTyFamEqLHS_maybe rhs
|
| ... | ... | @@ -2044,19 +2050,20 @@ What do we do when we have an equality |
| 2044 | 2050 | where k1 and k2 differ? Easy: we create a coercion that relates k1 and
|
| 2045 | 2051 | k2 and use this to cast. To wit, from
|
| 2046 | 2052 | |
| 2047 | - [X] (tv :: k1) ~ (rhs :: k2)
|
|
| 2053 | + [X] co1 :: (tv :: k1) ~ (rhs :: k2)
|
|
| 2048 | 2054 | |
| 2049 | 2055 | (where [X] is [G] or [W]), we go to
|
| 2050 | 2056 | |
| 2051 | - [X] co :: k1 ~ k2
|
|
| 2052 | - [X] (tv :: k1) ~ ((rhs |> sym co) :: k1)
|
|
| 2057 | + co1 = co2 ; sym (GRefl kco)
|
|
| 2058 | + [X] co2 :: (tv :: k1) ~ ((rhs |> sym kco) :: k1)
|
|
| 2059 | + [X] kco :: k1 ~ k2
|
|
| 2053 | 2060 | |
| 2054 | 2061 | Wrinkles:
|
| 2055 | 2062 | |
| 2056 | -(EIK1) When X is W, the new type-level wanted is effectively rewritten by the
|
|
| 2057 | - kind-level one. We thus include the kind-level wanted in the RewriterSet
|
|
| 2058 | - for the type-level one. See Note [Wanteds rewrite Wanteds] in GHC.Tc.Types.Constraint.
|
|
| 2059 | - This is done in canEqCanLHSHetero.
|
|
| 2063 | +(EIK1) When X=Wanted, the new type-level wanted for `co` is effectively rewritten by
|
|
| 2064 | + the kind-level one. We thus include the kind-level wanted in the RewriterSet
|
|
| 2065 | + for the type-level one. See Note [Wanteds rewrite Wanteds] in
|
|
| 2066 | + GHC.Tc.Types.Constraint. This is done in canEqCanLHSHetero.
|
|
| 2060 | 2067 | |
| 2061 | 2068 | (EIK2) Suppose we have [W] (a::Type) ~ (b::Type->Type). The above rewrite will produce
|
| 2062 | 2069 | [W] w : a ~ (b |> kw)
|
| ... | ... | @@ -2076,13 +2083,17 @@ Wrinkles: |
| 2076 | 2083 | Instead, it lands in the inert_irreds in the inert set, awaiting solution of
|
| 2077 | 2084 | that `kw`.
|
| 2078 | 2085 | |
| 2079 | - (EIK2a) We must later indeed unify if/when the kind-level wanted, `kw` gets
|
|
| 2080 | - solved. This is done in kickOutAfterFillingCoercionHole, which kicks out
|
|
| 2086 | + (EIK2a) We must later indeed unify if/when the kind-level wanted, `kw` gets
|
|
| 2087 | + solved. This is done in `kickOutAfterFillingCoercionHole`, which kicks out
|
|
| 2081 | 2088 | all equalities whose RHS mentions the filled-in coercion hole. Note that
|
| 2082 | 2089 | it looks for type family equalities, too, because of the use of unifyTest
|
| 2083 | 2090 | in canEqTyVarFunEq.
|
| 2084 | 2091 | |
| 2085 | - (EIK2b) What if the RHS mentions /other/ coercion holes? How can that happen? The
|
|
| 2092 | + To do this, we slightly-hackily use the `ctev_rewriters` field of the inert,
|
|
| 2093 | + which records that `w` has been rewritten by `kw`.
|
|
| 2094 | + See (WRW3) in Note [Wanteds rewrite Wanteds] in GHC.Tc.Types.Constraint.
|
|
| 2095 | + |
|
| 2096 | + (EIK2b) What if the RHS mentions /other/ coercion holes? How can that happen? The
|
|
| 2086 | 2097 | main way is like this. Assume F :: forall k. k -> Type
|
| 2087 | 2098 | [W] kw : k ~ Type
|
| 2088 | 2099 | [W] w : a ~ F k t
|
| ... | ... | @@ -2093,15 +2104,32 @@ Wrinkles: |
| 2093 | 2104 | rewriting. Indeed tests JuanLopez only typechecks if we do. So we'd like to treat
|
| 2094 | 2105 | this kind of equality as canonical.
|
| 2095 | 2106 | |
| 2096 | - Hence the ch_hetero_kind field in CoercionHole: it is True of constraints
|
|
| 2097 | - created by `canEqCanLHSHetero` to fix up hetero-kinded equalities; and False otherwise:
|
|
| 2107 | + So here is our implementation:
|
|
| 2108 | + * The `ch_hetero_kind` field in CoercionHole identifies a coercion hole created
|
|
| 2109 | + by `canEqCanLHSHetero` to fix up hetero-kinded equalities.
|
|
| 2110 | + |
|
| 2111 | + * An equality constraint is non-canonical if it mentions a /hetero-kind/
|
|
| 2112 | + CoercionHole on the RHS. This (and only this) is the (TyEq:CH) invariant
|
|
| 2113 | + for canonical equalities (see Note [Canonical equalities])
|
|
| 2114 | + |
|
| 2115 | + * The invariant is checked by the `hasHeterKindCoercionHoleCo` test in
|
|
| 2116 | + GHC.Tc.Utils.Unify.checkCo; and not satisfying this invariant is what
|
|
| 2117 | + `cteCoercionHole` in `CheckTyEqResult` means.
|
|
| 2098 | 2118 | |
| 2099 | - * An equality constraint is non-canonical if it mentions a hetero-kind
|
|
| 2100 | - CoercionHole on the RHS. See the `hasCoercionHoleCo` test in GHC.Tc.Utils.checkCo.
|
|
| 2119 | + * These special hetero-kind CoercionHoles are created by the `uType` unifier when
|
|
| 2120 | + the parent's CtOrigin is KindEqOrigin: see GHC.Tc.Utils.TcMType.newCoercionHole
|
|
| 2121 | + and friends.
|
|
| 2101 | 2122 | |
| 2102 | - * Hetero-kind CoercionHoles are created when the parent's CtOrigin is
|
|
| 2103 | - KindEqOrigin: see GHC.Tc.Utils.TcMType.newCoercionHole and friends. We
|
|
| 2104 | - set this origin, via `mkKindLoc`, in `mk_kind_eq` in `canEqCanLHSHetero`.
|
|
| 2123 | + We set this origin, via `updUEnvLoc`, in `mk_kind_eq` in `canEqCanLHSHetero`.
|
|
| 2124 | + |
|
| 2125 | + * We /also/ add the coercion hole to the `RewriterSet` of the constraint,
|
|
| 2126 | + in `canEqCanLHSHetero`
|
|
| 2127 | + |
|
| 2128 | + * When filling one of these special hetero-kind coercion holes, we kick out
|
|
| 2129 | + any IrredCt's that mention this hole; maybe it is now canonical.
|
|
| 2130 | + See `kickOutAfterFillingCoercionHole`.
|
|
| 2131 | + |
|
| 2132 | + Gah! This is bizarrely complicated.
|
|
| 2105 | 2133 | |
| 2106 | 2134 | (EIK3) Suppose we have [W] (a :: k1) ~ (rhs :: k2). We duly follow the
|
| 2107 | 2135 | algorithm detailed here, producing [W] co :: k1 ~ k2, and adding
|
| ... | ... | @@ -2576,17 +2604,17 @@ Suppose we have |
| 2576 | 2604 | Then we can simply solve g2 from g1, thus g2 := g1. Easy!
|
| 2577 | 2605 | But it's not so simple:
|
| 2578 | 2606 | |
| 2579 | -* If t is a type variable, the equalties might be oriented differently:
|
|
| 2607 | +(CE1) If t is a type variable, the equalties might be oriented differently:
|
|
| 2580 | 2608 | e.g. (g1 :: a~b) and (g2 :: b~a)
|
| 2581 | 2609 | So we look both ways round. Hence the SwapFlag result to
|
| 2582 | 2610 | inertsCanDischarge.
|
| 2583 | 2611 | |
| 2584 | -* We can only do g2 := g1 if g1 can discharge g2; that depends on
|
|
| 2612 | +(CE2) We can only do g2 := g1 if g1 can discharge g2; that depends on
|
|
| 2585 | 2613 | (a) the role and (b) the flavour. E.g. a representational equality
|
| 2586 | 2614 | cannot discharge a nominal one; a Wanted cannot discharge a Given.
|
| 2587 | 2615 | The predicate is eqCanRewriteFR.
|
| 2588 | 2616 | |
| 2589 | -* Visibility. Suppose S :: forall k. k -> Type, and consider unifying
|
|
| 2617 | +(CE3) Visibility. Suppose S :: forall k. k -> Type, and consider unifying
|
|
| 2590 | 2618 | S @Type (a::Type) ~ S @(Type->Type) (b::Type->Type)
|
| 2591 | 2619 | From the first argument we get (Type ~ Type->Type); from the second
|
| 2592 | 2620 | argument we get (a ~ b) which in turn gives (Type ~ Type->Type).
|
| ... | ... | @@ -2601,6 +2629,24 @@ But it's not so simple: |
| 2601 | 2629 | So when combining two otherwise-identical equalites, we want to
|
| 2602 | 2630 | keep the visible one, and discharge the invisible one. Hence the
|
| 2603 | 2631 | call to strictly_more_visible.
|
| 2632 | + |
|
| 2633 | +(CE4) Suppose we have this set up (#25440):
|
|
| 2634 | + Inert: [W] g1: F a ~ a Int (arising from (F a ~ a Int)
|
|
| 2635 | + Work item: [W] g2: F alpha ~ F a (arising from (F alpha ~ F a)
|
|
| 2636 | + We rewrite g2 with g1, to give
|
|
| 2637 | + [W] g2{rw:g1} : F alpha ~ a Int
|
|
| 2638 | + Now if F is injective we can get [W] alpha~a, and hence alpha:=a, and
|
|
| 2639 | + we kick out g1. Now we have two constraints
|
|
| 2640 | + [W] g1 : F a ~ a Int (arising from (F a ~ a Int)
|
|
| 2641 | + [W] g2{rw:g1} : F a ~ a Int (arising from (F alpha ~ F a)
|
|
| 2642 | + If we end up with g2 in the inert set (not g1) we'll get a very confusing
|
|
| 2643 | + error message that we can solve (F a ~ a Int)
|
|
| 2644 | + arising from F a ~ F a
|
|
| 2645 | + |
|
| 2646 | + TL;DR: Better to hang on to `g1` (with no rewriters), in preference
|
|
| 2647 | + to `g2` (which has a rewriter).
|
|
| 2648 | + |
|
| 2649 | + See (WRW1) in Note [Wanteds rewrite Wanteds] in GHC.Tc.Types.Constraint.
|
|
| 2604 | 2650 | -}
|
| 2605 | 2651 | |
| 2606 | 2652 | tryInertEqs :: EqCt -> SolverStage ()
|
| ... | ... | @@ -2646,21 +2692,27 @@ inertsCanDischarge inerts (EqCt { eq_lhs = lhs_w, eq_rhs = rhs_w |
| 2646 | 2692 | loc_w = ctEvLoc ev_w
|
| 2647 | 2693 | flav_w = ctEvFlavour ev_w
|
| 2648 | 2694 | fr_w = (flav_w, eq_rel)
|
| 2695 | + empty_rw_w = isEmptyRewriterSet (ctEvRewriters ev_w)
|
|
| 2649 | 2696 | |
| 2650 | 2697 | inert_beats_wanted ev_i eq_rel
|
| 2651 | 2698 | = -- eqCanRewriteFR: see second bullet of Note [Combining equalities]
|
| 2652 | - -- strictly_more_visible: see last bullet of Note [Combining equalities]
|
|
| 2653 | 2699 | fr_i `eqCanRewriteFR` fr_w
|
| 2654 | - && not ((loc_w `strictly_more_visible` ctEvLoc ev_i)
|
|
| 2655 | - && (fr_w `eqCanRewriteFR` fr_i))
|
|
| 2700 | + && not (prefer_wanted ev_i && (fr_w `eqCanRewriteFR` fr_i))
|
|
| 2656 | 2701 | where
|
| 2657 | 2702 | fr_i = (ctEvFlavour ev_i, eq_rel)
|
| 2658 | 2703 | |
| 2659 | - -- See Note [Combining equalities], final bullet
|
|
| 2704 | + -- See (CE3) in Note [Combining equalities]
|
|
| 2660 | 2705 | strictly_more_visible loc1 loc2
|
| 2661 | 2706 | = not (isVisibleOrigin (ctLocOrigin loc2)) &&
|
| 2662 | 2707 | isVisibleOrigin (ctLocOrigin loc1)
|
| 2663 | 2708 | |
| 2709 | + prefer_wanted ev_i
|
|
| 2710 | + = (loc_w `strictly_more_visible` ctEvLoc ev_i)
|
|
| 2711 | + -- strictly_more_visible: see (CE3) in Note [Combining equalities]
|
|
| 2712 | + || (empty_rw_w && not (isEmptyRewriterSet (ctEvRewriters ev_i)))
|
|
| 2713 | + -- Prefer the one that has no rewriters
|
|
| 2714 | + -- See (CE4) in Note [Combining equalities]
|
|
| 2715 | + |
|
| 2664 | 2716 | inertsCanDischarge _ _ = Nothing
|
| 2665 | 2717 | |
| 2666 | 2718 | |
| ... | ... | @@ -3017,6 +3069,7 @@ improve_wanted_top_fun_eqs fam_tc lhs_tys rhs_ty |
| 3017 | 3069 | |
| 3018 | 3070 | improve_injective_wanted_top :: FamInstEnvs -> [Bool] -> TyCon -> [TcType] -> Xi -> TcS [TypeEqn]
|
| 3019 | 3071 | -- Interact with top-level instance declarations
|
| 3072 | +-- See Section 5.2 in the Injective Type Families paper
|
|
| 3020 | 3073 | improve_injective_wanted_top fam_envs inj_args fam_tc lhs_tys rhs_ty
|
| 3021 | 3074 | = concatMapM do_one branches
|
| 3022 | 3075 | where
|
| ... | ... | @@ -3035,6 +3088,7 @@ improve_injective_wanted_top fam_envs inj_args fam_tc lhs_tys rhs_ty |
| 3035 | 3088 | do_one branch@(CoAxBranch { cab_tvs = branch_tvs, cab_lhs = branch_lhs_tys, cab_rhs = branch_rhs })
|
| 3036 | 3089 | | let in_scope1 = in_scope `extendInScopeSetList` branch_tvs
|
| 3037 | 3090 | , Just subst <- tcUnifyTyForInjectivity False in_scope1 branch_rhs rhs_ty
|
| 3091 | + -- False: matching, not unifying
|
|
| 3038 | 3092 | = do { let inSubst tv = tv `elemVarEnv` getTvSubstEnv subst
|
| 3039 | 3093 | unsubstTvs = filterOut inSubst branch_tvs
|
| 3040 | 3094 | -- The order of unsubstTvs is important; it must be
|
| ... | ... | @@ -9,9 +9,9 @@ module GHC.Tc.Solver.InertSet ( |
| 9 | 9 | extendWorkListNonEq, extendWorkListCt,
|
| 10 | 10 | extendWorkListCts, extendWorkListCtList,
|
| 11 | 11 | extendWorkListEq, extendWorkListEqs,
|
| 12 | + extendWorkListRewrittenEqs,
|
|
| 12 | 13 | appendWorkList, extendWorkListImplic,
|
| 13 | 14 | workListSize,
|
| 14 | - selectWorkItem,
|
|
| 15 | 15 | |
| 16 | 16 | -- * The inert set
|
| 17 | 17 | InertSet(..),
|
| ... | ... | @@ -172,6 +172,7 @@ See GHC.Tc.Solver.Monad.deferTcSForAllEq |
| 172 | 172 | data WorkList
|
| 173 | 173 | = WL { wl_eqs_N :: [Ct] -- /Nominal/ equalities (s ~#N t), (s ~ t), (s ~~ t)
|
| 174 | 174 | -- with empty rewriter set
|
| 175 | + |
|
| 175 | 176 | , wl_eqs_X :: [Ct] -- CEqCan, CDictCan, CIrredCan
|
| 176 | 177 | -- with empty rewriter set
|
| 177 | 178 | -- All other equalities: contains both equality constraints and
|
| ... | ... | @@ -179,9 +180,8 @@ data WorkList |
| 179 | 180 | -- See Note [Prioritise equalities]
|
| 180 | 181 | -- See Note [Prioritise class equalities]
|
| 181 | 182 | |
| 182 | - , wl_rw_eqs :: [Ct] -- Like wl_eqs, but ones that have a non-empty
|
|
| 183 | - -- rewriter set; or, more precisely, did when
|
|
| 184 | - -- added to the WorkList
|
|
| 183 | + , wl_rw_eqs :: [Ct] -- Like wl_eqs, but ones that may have a non-empty
|
|
| 184 | + -- rewriter set
|
|
| 185 | 185 | -- We prioritise wl_eqs over wl_rw_eqs;
|
| 186 | 186 | -- see Note [Prioritise Wanteds with empty RewriterSet]
|
| 187 | 187 | -- in GHC.Tc.Types.Constraint for more details.
|
| ... | ... | @@ -258,6 +258,11 @@ extendWorkListEqs rewriters new_eqs |
| 258 | 258 | -- push_on_front puts the new equlities on the front of the queue
|
| 259 | 259 | push_on_front new_eqs eqs = foldr (:) eqs new_eqs
|
| 260 | 260 | |
| 261 | +extendWorkListRewrittenEqs :: [EqCt] -> WorkList -> WorkList
|
|
| 262 | +-- Don't bother checking the RewriterSet: just pop them into wl_rw_eqs
|
|
| 263 | +extendWorkListRewrittenEqs new_eqs wl@(WL { wl_rw_eqs = rw_eqs })
|
|
| 264 | + = wl { wl_rw_eqs = foldr ((:) . CEqCan) rw_eqs new_eqs }
|
|
| 265 | + |
|
| 261 | 266 | extendWorkListNonEq :: Ct -> WorkList -> WorkList
|
| 262 | 267 | -- Extension by non equality
|
| 263 | 268 | extendWorkListNonEq ct wl = wl { wl_rest = ct : wl_rest wl }
|
| ... | ... | @@ -296,16 +301,6 @@ emptyWorkList :: WorkList |
| 296 | 301 | emptyWorkList = WL { wl_eqs_N = [], wl_eqs_X = []
|
| 297 | 302 | , wl_rw_eqs = [], wl_rest = [], wl_implics = emptyBag }
|
| 298 | 303 | |
| 299 | -selectWorkItem :: WorkList -> Maybe (Ct, WorkList)
|
|
| 300 | --- See Note [Prioritise equalities]
|
|
| 301 | -selectWorkItem wl@(WL { wl_eqs_N = eqs_N, wl_eqs_X = eqs_X
|
|
| 302 | - , wl_rw_eqs = rw_eqs, wl_rest = rest })
|
|
| 303 | - | ct:cts <- eqs_N = Just (ct, wl { wl_eqs_N = cts })
|
|
| 304 | - | ct:cts <- eqs_X = Just (ct, wl { wl_eqs_X = cts })
|
|
| 305 | - | ct:cts <- rw_eqs = Just (ct, wl { wl_rw_eqs = cts })
|
|
| 306 | - | ct:cts <- rest = Just (ct, wl { wl_rest = cts })
|
|
| 307 | - | otherwise = Nothing
|
|
| 308 | - |
|
| 309 | 304 | -- Pretty printing
|
| 310 | 305 | instance Outputable WorkList where
|
| 311 | 306 | ppr (WL { wl_eqs_N = eqs_N, wl_eqs_X = eqs_X, wl_rw_eqs = rw_eqs
|
| ... | ... | @@ -150,7 +150,6 @@ import qualified GHC.Tc.Utils.Env as TcM |
| 150 | 150 | )
|
| 151 | 151 | import GHC.Tc.Zonk.Monad ( ZonkM )
|
| 152 | 152 | import qualified GHC.Tc.Zonk.TcType as TcM
|
| 153 | -import qualified GHC.Tc.Zonk.Type as TcM
|
|
| 154 | 153 | |
| 155 | 154 | import GHC.Driver.DynFlags
|
| 156 | 155 | |
| ... | ... | @@ -475,16 +474,16 @@ kickOutAfterUnification tv_list = case nonEmpty tv_list of |
| 475 | 474 | ; return n_kicked }
|
| 476 | 475 | |
| 477 | 476 | kickOutAfterFillingCoercionHole :: CoercionHole -> TcS ()
|
| 478 | --- See Wrinkle (EIK2a) in Note [Equalities with incompatible kinds] in GHC.Tc.Solver.Equality
|
|
| 477 | +-- See Wrinkle (EIK2) in Note [Equalities with incompatible kinds] in GHC.Tc.Solver.Equality
|
|
| 479 | 478 | -- It's possible that this could just go ahead and unify, but could there be occurs-check
|
| 480 | 479 | -- problems? Seems simpler just to kick out.
|
| 481 | 480 | kickOutAfterFillingCoercionHole hole
|
| 482 | 481 | = do { ics <- getInertCans
|
| 483 | 482 | ; let (kicked_out, ics') = kick_out ics
|
| 484 | - n_kicked = lengthBag kicked_out
|
|
| 483 | + n_kicked = length kicked_out
|
|
| 485 | 484 | |
| 486 | 485 | ; unless (n_kicked == 0) $
|
| 487 | - do { updWorkListTcS (extendWorkListCts (fmap CIrredCan kicked_out))
|
|
| 486 | + do { updWorkListTcS (extendWorkListRewrittenEqs kicked_out)
|
|
| 488 | 487 | ; csTraceTcS $
|
| 489 | 488 | hang (text "Kick out, hole =" <+> ppr hole)
|
| 490 | 489 | 2 (vcat [ text "n-kicked =" <+> int n_kicked
|
| ... | ... | @@ -493,24 +492,18 @@ kickOutAfterFillingCoercionHole hole |
| 493 | 492 | |
| 494 | 493 | ; setInertCans ics' }
|
| 495 | 494 | where
|
| 496 | - kick_out :: InertCans -> (Bag IrredCt, InertCans)
|
|
| 497 | - kick_out ics@(IC { inert_irreds = irreds })
|
|
| 498 | - = -- We only care about irreds here, because any constraint blocked
|
|
| 499 | - -- by a coercion hole is an irred. See wrinkle (EIK2a) in
|
|
| 500 | - -- Note [Equalities with incompatible kinds] in GHC.Tc.Solver.Canonical
|
|
| 501 | - (irreds_to_kick, ics { inert_irreds = irreds_to_keep })
|
|
| 495 | + kick_out :: InertCans -> ([EqCt], InertCans)
|
|
| 496 | + kick_out ics@(IC { inert_eqs = eqs })
|
|
| 497 | + = (eqs_to_kick, ics { inert_eqs = eqs_to_keep })
|
|
| 502 | 498 | where
|
| 503 | - (irreds_to_kick, irreds_to_keep) = partitionBag kick_ct irreds
|
|
| 504 | - |
|
| 505 | - kick_ct :: IrredCt -> Bool
|
|
| 506 | - -- True: kick out; False: keep.
|
|
| 507 | - kick_ct ct
|
|
| 508 | - | IrredCt { ir_ev = ev, ir_reason = reason } <- ct
|
|
| 509 | - , CtWanted (WantedCt { ctev_rewriters = RewriterSet rewriters }) <- ev
|
|
| 510 | - , NonCanonicalReason ctyeq <- reason
|
|
| 511 | - , ctyeq `cterHasProblem` cteCoercionHole
|
|
| 512 | - , hole `elementOfUniqSet` rewriters
|
|
| 513 | - = True
|
|
| 499 | + (eqs_to_kick, eqs_to_keep) = partitionInertEqs kick_out_eq eqs
|
|
| 500 | + |
|
| 501 | + kick_out_eq :: EqCt -> Bool -- True: kick out; False: keep.
|
|
| 502 | + kick_out_eq (EqCt { eq_ev = ev ,eq_lhs = lhs })
|
|
| 503 | + | CtWanted (WantedCt { ctev_rewriters = RewriterSet rewriters }) <- ev
|
|
| 504 | + , TyVarLHS tv <- lhs
|
|
| 505 | + , isMetaTyVar tv
|
|
| 506 | + = hole `elementOfUniqSet` rewriters
|
|
| 514 | 507 | | otherwise
|
| 515 | 508 | = False
|
| 516 | 509 | |
| ... | ... | @@ -847,17 +840,15 @@ removeInertCt is ct |
| 847 | 840 | |
| 848 | 841 | -- | Looks up a family application in the inerts.
|
| 849 | 842 | lookupFamAppInert :: (CtFlavourRole -> Bool) -- can it rewrite the target?
|
| 850 | - -> TyCon -> [Type] -> TcS (Maybe (Reduction, CtFlavourRole))
|
|
| 843 | + -> TyCon -> [Type] -> TcS (Maybe EqCt)
|
|
| 851 | 844 | lookupFamAppInert rewrite_pred fam_tc tys
|
| 852 | 845 | = do { IS { inert_cans = IC { inert_funeqs = inert_funeqs } } <- getInertSet
|
| 853 | 846 | ; return (lookup_inerts inert_funeqs) }
|
| 854 | 847 | where
|
| 855 | 848 | lookup_inerts inert_funeqs
|
| 856 | - | Just ecl <- findFunEq inert_funeqs fam_tc tys
|
|
| 857 | - , Just (EqCt { eq_ev = ctev, eq_rhs = rhs })
|
|
| 858 | - <- find (rewrite_pred . eqCtFlavourRole) ecl
|
|
| 859 | - = Just (mkReduction (ctEvCoercion ctev) rhs, ctEvFlavourRole ctev)
|
|
| 860 | - | otherwise = Nothing
|
|
| 849 | + = case findFunEq inert_funeqs fam_tc tys of
|
|
| 850 | + Nothing -> Nothing
|
|
| 851 | + Just (ecl :: [EqCt]) -> find (rewrite_pred . eqCtFlavourRole) ecl
|
|
| 861 | 852 | |
| 862 | 853 | lookupInInerts :: CtLoc -> TcPredType -> TcS (Maybe CtEvidence)
|
| 863 | 854 | -- Is this exact predicate type cached in the solved or canonicals of the InertSet?
|
| ... | ... | @@ -1418,62 +1409,6 @@ getInertSet = getInertSetRef >>= readTcRef |
| 1418 | 1409 | setInertSet :: InertSet -> TcS ()
|
| 1419 | 1410 | setInertSet is = do { r <- getInertSetRef; writeTcRef r is }
|
| 1420 | 1411 | |
| 1421 | -getTcSWorkListRef :: TcS (IORef WorkList)
|
|
| 1422 | -getTcSWorkListRef = TcS (return . tcs_worklist)
|
|
| 1423 | - |
|
| 1424 | -getWorkListImplics :: TcS (Bag Implication)
|
|
| 1425 | -getWorkListImplics
|
|
| 1426 | - = do { wl_var <- getTcSWorkListRef
|
|
| 1427 | - ; wl_curr <- readTcRef wl_var
|
|
| 1428 | - ; return (wl_implics wl_curr) }
|
|
| 1429 | - |
|
| 1430 | -pushLevelNoWorkList :: SDoc -> TcS a -> TcS (TcLevel, a)
|
|
| 1431 | --- Push the level and run thing_inside
|
|
| 1432 | --- However, thing_inside should not generate any work items
|
|
| 1433 | -#if defined(DEBUG)
|
|
| 1434 | -pushLevelNoWorkList err_doc (TcS thing_inside)
|
|
| 1435 | - = TcS (\env -> TcM.pushTcLevelM $
|
|
| 1436 | - thing_inside (env { tcs_worklist = wl_panic })
|
|
| 1437 | - )
|
|
| 1438 | - where
|
|
| 1439 | - wl_panic = pprPanic "GHC.Tc.Solver.Monad.buildImplication" err_doc
|
|
| 1440 | - -- This panic checks that the thing-inside
|
|
| 1441 | - -- does not emit any work-list constraints
|
|
| 1442 | -#else
|
|
| 1443 | -pushLevelNoWorkList _ (TcS thing_inside)
|
|
| 1444 | - = TcS (\env -> TcM.pushTcLevelM (thing_inside env)) -- Don't check
|
|
| 1445 | -#endif
|
|
| 1446 | - |
|
| 1447 | -updWorkListTcS :: (WorkList -> WorkList) -> TcS ()
|
|
| 1448 | -updWorkListTcS f
|
|
| 1449 | - = do { wl_var <- getTcSWorkListRef
|
|
| 1450 | - ; updTcRef wl_var f }
|
|
| 1451 | - |
|
| 1452 | -emitWorkNC :: [CtEvidence] -> TcS ()
|
|
| 1453 | -emitWorkNC evs
|
|
| 1454 | - | null evs
|
|
| 1455 | - = return ()
|
|
| 1456 | - | otherwise
|
|
| 1457 | - = emitWork (listToBag (map mkNonCanonical evs))
|
|
| 1458 | - |
|
| 1459 | -emitWork :: Cts -> TcS ()
|
|
| 1460 | -emitWork cts
|
|
| 1461 | - | isEmptyBag cts -- Avoid printing, among other work
|
|
| 1462 | - = return ()
|
|
| 1463 | - | otherwise
|
|
| 1464 | - = do { traceTcS "Emitting fresh work" (pprBag cts)
|
|
| 1465 | - -- Zonk the rewriter set of Wanteds, because that affects
|
|
| 1466 | - -- the prioritisation of the work-list. Suppose a constraint
|
|
| 1467 | - -- c1 is rewritten by another, c2. When c2 gets solved,
|
|
| 1468 | - -- c1 has no rewriters, and can be prioritised; see
|
|
| 1469 | - -- Note [Prioritise Wanteds with empty RewriterSet]
|
|
| 1470 | - -- in GHC.Tc.Types.Constraint wrinkle (WRW1)
|
|
| 1471 | - ; cts <- wrapTcS $ mapBagM TcM.zonkCtRewriterSet cts
|
|
| 1472 | - ; updWorkListTcS (extendWorkListCts cts) }
|
|
| 1473 | - |
|
| 1474 | -emitImplication :: Implication -> TcS ()
|
|
| 1475 | -emitImplication implic
|
|
| 1476 | - = updWorkListTcS (extendWorkListImplic implic)
|
|
| 1477 | 1412 | |
| 1478 | 1413 | newTcRef :: a -> TcS (TcRef a)
|
| 1479 | 1414 | newTcRef x = wrapTcS (TcM.newTcRef x)
|
| ... | ... | @@ -1532,23 +1467,6 @@ reportUnifications (TcS thing_inside) |
| 1532 | 1467 | getDefaultInfo :: TcS (DefaultEnv, Bool)
|
| 1533 | 1468 | getDefaultInfo = wrapTcS TcM.tcGetDefaultTys
|
| 1534 | 1469 | |
| 1535 | -getWorkList :: TcS WorkList
|
|
| 1536 | -getWorkList = do { wl_var <- getTcSWorkListRef
|
|
| 1537 | - ; wrapTcS (TcM.readTcRef wl_var) }
|
|
| 1538 | - |
|
| 1539 | -selectNextWorkItem :: TcS (Maybe Ct)
|
|
| 1540 | --- Pick which work item to do next
|
|
| 1541 | --- See Note [Prioritise equalities]
|
|
| 1542 | -selectNextWorkItem
|
|
| 1543 | - = do { wl_var <- getTcSWorkListRef
|
|
| 1544 | - ; wl <- readTcRef wl_var
|
|
| 1545 | - ; case selectWorkItem wl of {
|
|
| 1546 | - Nothing -> return Nothing ;
|
|
| 1547 | - Just (ct, new_wl) ->
|
|
| 1548 | - do { -- checkReductionDepth (ctLoc ct) (ctPred ct)
|
|
| 1549 | - -- This is done by GHC.Tc.Solver.Dict.chooseInstance
|
|
| 1550 | - ; writeTcRef wl_var new_wl
|
|
| 1551 | - ; return (Just ct) } } }
|
|
| 1552 | 1470 | |
| 1553 | 1471 | -- Just get some environments needed for instance looking up and matching
|
| 1554 | 1472 | -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -1805,6 +1723,116 @@ pprKicked :: Int -> SDoc |
| 1805 | 1723 | pprKicked 0 = empty
|
| 1806 | 1724 | pprKicked n = parens (int n <+> text "kicked out")
|
| 1807 | 1725 | |
| 1726 | + |
|
| 1727 | +{- *********************************************************************
|
|
| 1728 | +* *
|
|
| 1729 | +* The work list
|
|
| 1730 | +* *
|
|
| 1731 | +********************************************************************* -}
|
|
| 1732 | + |
|
| 1733 | + |
|
| 1734 | +getTcSWorkListRef :: TcS (IORef WorkList)
|
|
| 1735 | +getTcSWorkListRef = TcS (return . tcs_worklist)
|
|
| 1736 | + |
|
| 1737 | +getWorkList :: TcS WorkList
|
|
| 1738 | +getWorkList = do { wl_var <- getTcSWorkListRef
|
|
| 1739 | + ; readTcRef wl_var }
|
|
| 1740 | + |
|
| 1741 | +getWorkListImplics :: TcS (Bag Implication)
|
|
| 1742 | +getWorkListImplics
|
|
| 1743 | + = do { wl_var <- getTcSWorkListRef
|
|
| 1744 | + ; wl_curr <- readTcRef wl_var
|
|
| 1745 | + ; return (wl_implics wl_curr) }
|
|
| 1746 | + |
|
| 1747 | +updWorkListTcS :: (WorkList -> WorkList) -> TcS ()
|
|
| 1748 | +updWorkListTcS f
|
|
| 1749 | + = do { wl_var <- getTcSWorkListRef
|
|
| 1750 | + ; updTcRef wl_var f }
|
|
| 1751 | + |
|
| 1752 | +emitWorkNC :: [CtEvidence] -> TcS ()
|
|
| 1753 | +emitWorkNC evs
|
|
| 1754 | + | null evs
|
|
| 1755 | + = return ()
|
|
| 1756 | + | otherwise
|
|
| 1757 | + = emitWork (listToBag (map mkNonCanonical evs))
|
|
| 1758 | + |
|
| 1759 | +emitWork :: Cts -> TcS ()
|
|
| 1760 | +emitWork cts
|
|
| 1761 | + | isEmptyBag cts -- Avoid printing, among other work
|
|
| 1762 | + = return ()
|
|
| 1763 | + | otherwise
|
|
| 1764 | + = do { traceTcS "Emitting fresh work" (pprBag cts)
|
|
| 1765 | + ; updWorkListTcS (extendWorkListCts cts) }
|
|
| 1766 | + |
|
| 1767 | +emitImplication :: Implication -> TcS ()
|
|
| 1768 | +emitImplication implic
|
|
| 1769 | + = updWorkListTcS (extendWorkListImplic implic)
|
|
| 1770 | + |
|
| 1771 | +selectNextWorkItem :: TcS (Maybe Ct)
|
|
| 1772 | +-- Pick which work item to do next
|
|
| 1773 | +-- See Note [Prioritise equalities]
|
|
| 1774 | +--
|
|
| 1775 | +-- Postcondition: if the returned item is a Wanted equality,
|
|
| 1776 | +-- then its rewriter set is fully zonked.
|
|
| 1777 | +--
|
|
| 1778 | +-- Suppose a constraint c1 is rewritten by another, c2. When c2
|
|
| 1779 | +-- gets solved, c1 has no rewriters, and can be prioritised; see
|
|
| 1780 | +-- Note [Prioritise Wanteds with empty RewriterSet] in
|
|
| 1781 | +-- GHC.Tc.Types.Constraint wrinkle (PER1)
|
|
| 1782 | + |
|
| 1783 | +-- ToDo: if wl_rw_eqs is long, we'll re-zonk it each time we pick
|
|
| 1784 | +-- a new item from wl_rest. Bad.
|
|
| 1785 | +selectNextWorkItem
|
|
| 1786 | + = do { wl_var <- getTcSWorkListRef
|
|
| 1787 | + ; wl <- readTcRef wl_var
|
|
| 1788 | + |
|
| 1789 | + ; case wl of { WL { wl_eqs_N = eqs_N, wl_eqs_X = eqs_X
|
|
| 1790 | + , wl_rw_eqs = rw_eqs, wl_rest = rest }
|
|
| 1791 | + | ct:cts <- eqs_N -> pick_me ct (wl { wl_eqs_N = cts })
|
|
| 1792 | + | ct:cts <- eqs_X -> pick_me ct (wl { wl_eqs_X = cts })
|
|
| 1793 | + | otherwise -> try_rws [] rw_eqs
|
|
| 1794 | + where
|
|
| 1795 | + pick_me :: Ct -> WorkList -> TcS (Maybe Ct)
|
|
| 1796 | + pick_me ct new_wl
|
|
| 1797 | + = do { writeTcRef wl_var new_wl
|
|
| 1798 | + ; return (Just ct) }
|
|
| 1799 | + -- NB: no need for checkReductionDepth (ctLoc ct) (ctPred ct)
|
|
| 1800 | + -- This is done by GHC.Tc.Solver.Dict.chooseInstance
|
|
| 1801 | + |
|
| 1802 | + -- try_rws looks through rw_eqs to find one that has an empty
|
|
| 1803 | + -- rewriter set, after zonking. If none such, call try_rest.
|
|
| 1804 | + try_rws acc (ct:cts)
|
|
| 1805 | + = do { ct' <- liftZonkTcS (TcM.zonkCtRewriterSet ct)
|
|
| 1806 | + ; if ctHasNoRewriters ct'
|
|
| 1807 | + then pick_me ct' (wl { wl_rw_eqs = cts ++ acc })
|
|
| 1808 | + else try_rws (ct':acc) cts }
|
|
| 1809 | + try_rws acc [] = try_rest acc
|
|
| 1810 | + |
|
| 1811 | + try_rest zonked_rws
|
|
| 1812 | + | ct:cts <- rest = pick_me ct (wl { wl_rw_eqs = zonked_rws, wl_rest = cts })
|
|
| 1813 | + | ct:cts <- zonked_rws = pick_me ct (wl { wl_rw_eqs = cts })
|
|
| 1814 | + | otherwise = return Nothing
|
|
| 1815 | + } }
|
|
| 1816 | + |
|
| 1817 | + |
|
| 1818 | +pushLevelNoWorkList :: SDoc -> TcS a -> TcS (TcLevel, a)
|
|
| 1819 | +-- Push the level and run thing_inside
|
|
| 1820 | +-- However, thing_inside should not generate any work items
|
|
| 1821 | +#if defined(DEBUG)
|
|
| 1822 | +pushLevelNoWorkList err_doc (TcS thing_inside)
|
|
| 1823 | + = TcS (\env -> TcM.pushTcLevelM $
|
|
| 1824 | + thing_inside (env { tcs_worklist = wl_panic })
|
|
| 1825 | + )
|
|
| 1826 | + where
|
|
| 1827 | + wl_panic = pprPanic "GHC.Tc.Solver.Monad.buildImplication" err_doc
|
|
| 1828 | + -- This panic checks that the thing-inside
|
|
| 1829 | + -- does not emit any work-list constraints
|
|
| 1830 | +#else
|
|
| 1831 | +pushLevelNoWorkList _ (TcS thing_inside)
|
|
| 1832 | + = TcS (\env -> TcM.pushTcLevelM (thing_inside env)) -- Don't check
|
|
| 1833 | +#endif
|
|
| 1834 | + |
|
| 1835 | + |
|
| 1808 | 1836 | {- *********************************************************************
|
| 1809 | 1837 | * *
|
| 1810 | 1838 | * The Unification Level Flag *
|
| ... | ... | @@ -2340,7 +2368,7 @@ wrapUnifierX ev role do_unifications |
| 2340 | 2368 | ; wrapTcS $
|
| 2341 | 2369 | do { defer_ref <- TcM.newTcRef emptyBag
|
| 2342 | 2370 | ; unified_ref <- TcM.newTcRef []
|
| 2343 | - ; rewriters <- TcM.zonkRewriterSet (ctEvRewriters ev)
|
|
| 2371 | + ; rewriters <- TcM.liftZonkM (TcM.zonkRewriterSet (ctEvRewriters ev))
|
|
| 2344 | 2372 | ; let env = UE { u_role = role
|
| 2345 | 2373 | , u_rewriters = rewriters
|
| 2346 | 2374 | , u_loc = ctEvLoc ev
|
| ... | ... | @@ -150,13 +150,16 @@ bumpDepth (RewriteM thing_inside) |
| 150 | 150 | { let !env' = env { re_loc = bumpCtLocDepth (re_loc env) }
|
| 151 | 151 | ; thing_inside env' }
|
| 152 | 152 | |
| 153 | +recordRewriter :: CtEvidence -> RewriteM ()
|
|
| 154 | +-- Record that we have rewritten the target with this (equality) evidence
|
|
| 153 | 155 | -- See Note [Wanteds rewrite Wanteds] in GHC.Tc.Types.Constraint
|
| 154 | --- Precondition: the WantedCtEvidence is for an equality constraint
|
|
| 155 | -recordRewriter :: WantedCtEvidence -> RewriteM ()
|
|
| 156 | -recordRewriter (WantedCt { ctev_dest = HoleDest hole })
|
|
| 157 | - = RewriteM $ \env -> updTcRef (re_rewriters env) (`addRewriter` hole)
|
|
| 158 | -recordRewriter other =
|
|
| 159 | - pprPanic "recordRewriter: non-equality constraint" (ppr other)
|
|
| 156 | +-- Precondition: the CtEvidence is for an equality constraint
|
|
| 157 | +recordRewriter (CtGiven {})
|
|
| 158 | + = return ()
|
|
| 159 | +recordRewriter (CtWanted (WantedCt { ctev_dest = dest }))
|
|
| 160 | + = case dest of
|
|
| 161 | + HoleDest hole -> RewriteM $ \env -> updTcRef (re_rewriters env) (`addRewriter` hole)
|
|
| 162 | + other -> pprPanic "recordRewriter: non-equality constraint" (ppr other)
|
|
| 160 | 163 | |
| 161 | 164 | {- Note [Rewriter EqRels]
|
| 162 | 165 | ~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -848,16 +851,18 @@ rewrite_exact_fam_app tc tys |
| 848 | 851 | |
| 849 | 852 | -- STEP 3: try the inerts
|
| 850 | 853 | ; flavour <- getFlavour
|
| 851 | - ; result2 <- liftTcS $ lookupFamAppInert (`eqCanRewriteFR` (flavour, eq_rel)) tc xis
|
|
| 852 | - ; case result2 of
|
|
| 853 | - { Just (redn, (inert_flavour, inert_eq_rel))
|
|
| 854 | + ; mb_eq <- liftTcS $ lookupFamAppInert (`eqCanRewriteFR` (flavour, eq_rel)) tc xis
|
|
| 855 | + ; case mb_eq of
|
|
| 856 | + { Just (EqCt { eq_ev = inert_ev, eq_rhs = inert_rhs, eq_eq_rel = inert_eq_rel })
|
|
| 854 | 857 | -> do { traceRewriteM "rewrite family application with inert"
|
| 855 | 858 | (ppr tc <+> ppr xis $$ ppr redn)
|
| 856 | - ; finish (inert_flavour == Given) (homogenise downgraded_redn) }
|
|
| 857 | - -- this will sometimes duplicate an inert in the cache,
|
|
| 859 | + ; recordRewriter inert_ev
|
|
| 860 | + ; finish (isGiven inert_ev) (homogenise downgraded_redn) }
|
|
| 861 | + -- This will sometimes duplicate an inert in the cache,
|
|
| 858 | 862 | -- but avoiding doing so had no impact on performance, and
|
| 859 | 863 | -- it seems easier not to weed out that special case
|
| 860 | 864 | where
|
| 865 | + redn = mkReduction (ctEvCoercion inert_ev) inert_rhs
|
|
| 861 | 866 | inert_role = eqRelRole inert_eq_rel
|
| 862 | 867 | role = eqRelRole eq_rel
|
| 863 | 868 | downgraded_redn = downgradeRedn role inert_role redn
|
| ... | ... | @@ -1024,11 +1029,8 @@ rewrite_tyvar2 tv fr@(_, eq_rel) |
| 1024 | 1029 | -> do { traceRewriteM "Following inert tyvar" $
|
| 1025 | 1030 | vcat [ ppr tv <+> equals <+> ppr rhs_ty
|
| 1026 | 1031 | , ppr ctev ]
|
| 1027 | - ; case ctev of
|
|
| 1028 | - CtGiven {} -> return ()
|
|
| 1029 | - CtWanted wtd ->
|
|
| 1032 | + ; recordRewriter ctev
|
|
| 1030 | 1033 | -- See Note [Wanteds rewrite Wanteds] in GHC.Tc.Types.Constraint
|
| 1031 | - recordRewriter wtd
|
|
| 1032 | 1034 | |
| 1033 | 1035 | ; let rewriting_co1 = ctEvCoercion ctev
|
| 1034 | 1036 | rewriting_co = case (ct_eq_rel, eq_rel) of
|
| ... | ... | @@ -17,7 +17,7 @@ module GHC.Tc.Types.Constraint ( |
| 17 | 17 | isUnsatisfiableCt_maybe,
|
| 18 | 18 | ctEvidence, updCtEvidence,
|
| 19 | 19 | ctLoc, ctPred, ctFlavour, ctEqRel, ctOrigin,
|
| 20 | - ctRewriters,
|
|
| 20 | + ctRewriters, ctHasNoRewriters,
|
|
| 21 | 21 | ctEvId, wantedEvId_maybe, mkTcEqPredLikeEv,
|
| 22 | 22 | mkNonCanonical, mkGivens,
|
| 23 | 23 | tyCoVarsOfCt, tyCoVarsOfCts,
|
| ... | ... | @@ -240,18 +240,24 @@ instance Outputable DictCt where |
| 240 | 240 | {- Note [Canonical equalities]
|
| 241 | 241 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 242 | 242 | An EqCt is a canonical equality constraint, one that can live in the inert set,
|
| 243 | -and that can be used to rewrite other constrtaints. It satisfies these invariants:
|
|
| 243 | +and that can be used to rewrite other constraints. It satisfies these invariants:
|
|
| 244 | + |
|
| 244 | 245 | * (TyEq:OC) lhs does not occur in rhs (occurs check)
|
| 245 | 246 | Note [EqCt occurs check]
|
| 247 | + |
|
| 246 | 248 | * (TyEq:F) rhs has no foralls
|
| 247 | 249 | (this avoids substituting a forall for the tyvar in other types)
|
| 250 | + |
|
| 248 | 251 | * (TyEq:K) typeKind lhs `tcEqKind` typeKind rhs; Note [Ct kind invariant]
|
| 252 | + |
|
| 249 | 253 | * (TyEq:N) If the equality is representational, rhs is not headed by a saturated
|
| 250 | 254 | application of a newtype TyCon. See GHC.Tc.Solver.Equality
|
| 251 | 255 | Note [No top-level newtypes on RHS of representational equalities].
|
| 252 | 256 | (Applies only when constructor of newtype is in scope.)
|
| 257 | + |
|
| 253 | 258 | * (TyEq:U) An EqCt is not immediately unifiable. If we can unify a:=ty, we
|
| 254 | 259 | will not form an EqCt (a ~ ty).
|
| 260 | + |
|
| 255 | 261 | * (TyEq:CH) rhs does not mention any coercion holes that resulted from fixing up
|
| 256 | 262 | a hetero-kinded equality. See Note [Equalities with incompatible kinds] in
|
| 257 | 263 | GHC.Tc.Solver.Equality, wrinkle (EIK2)
|
| ... | ... | @@ -534,9 +540,12 @@ cteSolubleOccurs = CTEP (bit 3) -- Occurs-check under a type function, or in |
| 534 | 540 | -- cteSolubleOccurs must be one bit to the left of cteInsolubleOccurs
|
| 535 | 541 | -- See also Note [Insoluble mis-match] in GHC.Tc.Errors
|
| 536 | 542 | |
| 537 | -cteCoercionHole = CTEP (bit 4) -- Coercion hole encountered
|
|
| 543 | +cteCoercionHole = CTEP (bit 4) -- Kind-equality coercion hole encountered
|
|
| 544 | + -- See (EIK2) in Note [Equalities with incompatible kinds]
|
|
| 545 | + |
|
| 538 | 546 | cteConcrete = CTEP (bit 5) -- Type variable that can't be made concrete
|
| 539 | 547 | -- e.g. alpha[conc] ~ Maybe beta[tv]
|
| 548 | + |
|
| 540 | 549 | cteSkolemEscape = CTEP (bit 6) -- Skolem escape e.g. alpha[2] ~ b[sk,4]
|
| 541 | 550 | |
| 542 | 551 | cteProblem :: CheckTyEqProblem -> CheckTyEqResult
|
| ... | ... | @@ -2220,6 +2229,12 @@ ctEvRewriters :: CtEvidence -> RewriterSet |
| 2220 | 2229 | ctEvRewriters (CtWanted (WantedCt { ctev_rewriters = rws })) = rws
|
| 2221 | 2230 | ctEvRewriters (CtGiven {}) = emptyRewriterSet
|
| 2222 | 2231 | |
| 2232 | +ctHasNoRewriters :: Ct -> Bool
|
|
| 2233 | +ctHasNoRewriters ct
|
|
| 2234 | + = case ctEvidence ct of
|
|
| 2235 | + CtWanted (WantedCt { ctev_rewriters = rws }) -> isEmptyRewriterSet rws
|
|
| 2236 | + CtGiven {} -> True
|
|
| 2237 | + |
|
| 2223 | 2238 | -- | Set the rewriter set of a Wanted constraint.
|
| 2224 | 2239 | setWantedCtEvRewriters :: WantedCtEvidence -> RewriterSet -> WantedCtEvidence
|
| 2225 | 2240 | setWantedCtEvRewriters ev rs = ev { ctev_rewriters = rs }
|
| ... | ... | @@ -2444,19 +2459,29 @@ We thus want Wanteds to rewrite Wanteds in order to accept more programs, |
| 2444 | 2459 | but we don't want Wanteds to rewrite Wanteds because doing so can create
|
| 2445 | 2460 | inscrutable error messages. To solve this dilemma:
|
| 2446 | 2461 | |
| 2447 | -* We allow Wanteds to rewrite Wanteds, but...
|
|
| 2462 | +* We allow Wanteds to rewrite Wanteds, but each Wanted tracks the set of Wanteds
|
|
| 2463 | + it has been rewritten by, in its RewriterSet, stored in the ctev_rewriters
|
|
| 2464 | + field of the CtWanted constructor of CtEvidence. (Only Wanteds have
|
|
| 2465 | + RewriterSets.)
|
|
| 2466 | + |
|
| 2467 | +* A RewriterSet is just a set of unfilled CoercionHoles. This is sufficient
|
|
| 2468 | + because only equalities (evidenced by coercion holes) are used for rewriting;
|
|
| 2469 | + other (dictionary) constraints cannot ever rewrite.
|
|
| 2470 | + |
|
| 2471 | +* The rewriter (in e.g. GHC.Tc.Solver.Rewrite.rewrite) tracks and returns a RewriterSet,
|
|
| 2472 | + consisting of the evidence (a CoercionHole) for any Wanted equalities used in
|
|
| 2473 | + rewriting.
|
|
| 2448 | 2474 | |
| 2449 | -* Each Wanted tracks the set of Wanteds it has been rewritten by, in its
|
|
| 2450 | - RewriterSet, stored in the ctev_rewriters field of the CtWanted
|
|
| 2451 | - constructor of CtEvidence. (Only Wanteds have RewriterSets.)
|
|
| 2475 | +* Then GHC.Tc.Solver.Solve.rewriteEvidence and GHC.Tc.Solver.Equality.rewriteEqEvidence
|
|
| 2476 | + add this RewriterSet to the rewritten constraint's rewriter set.
|
|
| 2452 | 2477 | |
| 2453 | 2478 | * In error reporting, we simply suppress any errors that have been rewritten
|
| 2454 | 2479 | by /unsolved/ wanteds. This suppression happens in GHC.Tc.Errors.mkErrorItem,
|
| 2455 | - which uses GHC.Tc.Zonk.Type.zonkRewriterSet to look through any filled
|
|
| 2480 | + which uses `GHC.Tc.Zonk.Type.zonkRewriterSet` to look through any filled
|
|
| 2456 | 2481 | coercion holes. The idea is that we wish to report the "root cause" -- the
|
| 2457 | 2482 | error that rewrote all the others.
|
| 2458 | 2483 | |
| 2459 | -* We prioritise Wanteds that have an empty RewriterSet:
|
|
| 2484 | +* In error reporting, we prioritise Wanteds that have an empty RewriterSet:
|
|
| 2460 | 2485 | see Note [Prioritise Wanteds with empty RewriterSet].
|
| 2461 | 2486 | |
| 2462 | 2487 | Let's continue our first example above:
|
| ... | ... | @@ -2471,19 +2496,30 @@ Because Wanteds can rewrite Wanteds, w1 will rewrite w2, yielding |
| 2471 | 2496 | |
| 2472 | 2497 | The {w1} in the second line of output is the RewriterSet of w1.
|
| 2473 | 2498 | |
| 2474 | -A RewriterSet is just a set of unfilled CoercionHoles. This is sufficient
|
|
| 2475 | -because only equalities (evidenced by coercion holes) are used for rewriting;
|
|
| 2476 | -other (dictionary) constraints cannot ever rewrite. The rewriter (in
|
|
| 2477 | -e.g. GHC.Tc.Solver.Rewrite.rewrite) tracks and returns a RewriterSet,
|
|
| 2478 | -consisting of the evidence (a CoercionHole) for any Wanted equalities used in
|
|
| 2479 | -rewriting. Then GHC.Tc.Solver.Solve.rewriteEvidence and
|
|
| 2480 | -GHC.Tc.Solver.Equality.rewriteEqEvidence add this RewriterSet to the rewritten
|
|
| 2481 | -constraint's rewriter set.
|
|
| 2499 | +Wrinkles:
|
|
| 2500 | + |
|
| 2501 | +(WRW1) When we find a constraint identical to one already in the inert set,
|
|
| 2502 | + we solve one from the other. Other things being equal, keep the one
|
|
| 2503 | + that has fewer (better still no) rewriters.
|
|
| 2504 | + See (CE4) in Note [Combining equalities] in GHC.Tc.Solver.Equality.
|
|
| 2505 | + |
|
| 2506 | + To this accurately we should use `zonkRewriterSet` during canonicalisation,
|
|
| 2507 | + to eliminate rewriters that have now been solved. Currently we only do so
|
|
| 2508 | + during error reporting; but perhaps we should change that.
|
|
| 2509 | + |
|
| 2510 | +(WRW2) When zonking a constraint (with `zonkCt` and `zonkCtEvidence`) we take
|
|
| 2511 | + the opportunity to zonk its `RewriterSet`, which eliminates solved ones.
|
|
| 2512 | + This doesn't guarantee that rewriter sets are always up to date -- see
|
|
| 2513 | + (WRW1) -- but it helps, and it de-clutters debug output.
|
|
| 2514 | + |
|
| 2515 | +(WRW3) We use the rewriter set for a slightly different purpose, in (EIK2)
|
|
| 2516 | + of Note [Equalities with incompatible kinds] in GHC.Tc.Solver.Equality.
|
|
| 2517 | + This is a bit of a hack.
|
|
| 2482 | 2518 | |
| 2483 | 2519 | Note [Prioritise Wanteds with empty RewriterSet]
|
| 2484 | 2520 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 2485 | 2521 | When extending the WorkList, in GHC.Tc.Solver.InertSet.extendWorkListEq,
|
| 2486 | -we priorities constraints that have no rewriters. Here's why.
|
|
| 2522 | +we prioritise constraints that have no rewriters. Here's why.
|
|
| 2487 | 2523 | |
| 2488 | 2524 | Consider this, which came up in T22793:
|
| 2489 | 2525 | inert: {}
|
| ... | ... | @@ -2527,11 +2563,11 @@ GHC.Tc.Solver.InertSet.extendWorkListEq, and extendWorkListEqs. |
| 2527 | 2563 | |
| 2528 | 2564 | Wrinkles
|
| 2529 | 2565 | |
| 2530 | -(WRW1) Before checking for an empty RewriterSet, we zonk the RewriterSet,
|
|
| 2566 | +(PER1) Before checking for an empty RewriterSet, we zonk the RewriterSet,
|
|
| 2531 | 2567 | because some of those CoercionHoles may have been filled in since we last
|
| 2532 | 2568 | looked: see GHC.Tc.Solver.Monad.emitWork.
|
| 2533 | 2569 | |
| 2534 | -(WRW2) Despite the prioritisation, it is hard to be /certain/ that we can't end up
|
|
| 2570 | +(PER2) Despite the prioritisation, it is hard to be /certain/ that we can't end up
|
|
| 2535 | 2571 | in a situation where all of the Wanteds have rewritten each other. In
|
| 2536 | 2572 | order to report /some/ error in this case, we simply report all the
|
| 2537 | 2573 | Wanteds. The user will get a perhaps-confusing error message, but they've
|
| ... | ... | @@ -49,7 +49,6 @@ module GHC.Tc.Utils.TcMType ( |
| 49 | 49 | |
| 50 | 50 | newCoercionHole, newCoercionHoleO, newVanillaCoercionHole,
|
| 51 | 51 | fillCoercionHole, isFilledCoercionHole,
|
| 52 | - unpackCoercionHole, unpackCoercionHole_maybe,
|
|
| 53 | 52 | checkCoercionHole,
|
| 54 | 53 | |
| 55 | 54 | newImplication,
|
| ... | ... | @@ -115,7 +114,6 @@ import GHC.Tc.Types.CtLoc( CtLoc, ctLocOrigin ) |
| 115 | 114 | import GHC.Tc.Utils.Monad -- TcType, amongst others
|
| 116 | 115 | import GHC.Tc.Utils.TcType
|
| 117 | 116 | import GHC.Tc.Errors.Types
|
| 118 | -import GHC.Tc.Zonk.Type
|
|
| 119 | 117 | import GHC.Tc.Zonk.TcType
|
| 120 | 118 | |
| 121 | 119 | import GHC.Builtin.Names
|
| ... | ... | @@ -371,6 +369,7 @@ newCoercionHoleO (KindEqOrigin {}) pty = new_coercion_hole True pty |
| 371 | 369 | newCoercionHoleO _ pty = new_coercion_hole False pty
|
| 372 | 370 | |
| 373 | 371 | new_coercion_hole :: Bool -> TcPredType -> TcM CoercionHole
|
| 372 | +-- For the Bool, see (EIK2) in Note [Equalities with incompatible kinds]
|
|
| 374 | 373 | new_coercion_hole hetero_kind pred_ty
|
| 375 | 374 | = do { co_var <- newEvVar pred_ty
|
| 376 | 375 | ; traceTc "New coercion hole:" (ppr co_var <+> dcolon <+> ppr pred_ty)
|
| ... | ... | @@ -1583,7 +1582,7 @@ collect_cand_qtvs_co orig_ty cur_lvl bound = go_co |
| 1583 | 1582 | go_co dv (SubCo co) = go_co dv co
|
| 1584 | 1583 | |
| 1585 | 1584 | go_co dv (HoleCo hole)
|
| 1586 | - = do m_co <- unpackCoercionHole_maybe hole
|
|
| 1585 | + = do m_co <- liftZonkM (unpackCoercionHole_maybe hole)
|
|
| 1587 | 1586 | case m_co of
|
| 1588 | 1587 | Just co -> go_co dv co
|
| 1589 | 1588 | Nothing -> go_cv dv (coHoleCoVar hole)
|
| ... | ... | @@ -2649,8 +2649,9 @@ There are five reasons not to unify: |
| 2649 | 2649 | we can fill beta[tau] := beta[conc]. This is why we call
|
| 2650 | 2650 | 'makeTypeConcrete' in startSolvingByUnification.
|
| 2651 | 2651 | |
| 2652 | -5. (COERCION-HOLE) Confusing coercion holes
|
|
| 2653 | - Suppose our equality is
|
|
| 2652 | +5. (COERCION-HOLE) rhs does not mention any coercion holes that resulted from
|
|
| 2653 | + fixing up a hetero-kinded equality. This is the same as (TyEq:CH) in
|
|
| 2654 | + Note [Canonical equalities]. Suppose our equality is
|
|
| 2654 | 2655 | (alpha :: k) ~ (Int |> {co})
|
| 2655 | 2656 | where co :: Type ~ k is an unsolved wanted. Note that this equality
|
| 2656 | 2657 | is homogeneous; both sides have kind k. We refrain from unifying here, because
|
| ... | ... | @@ -3546,11 +3547,13 @@ checkCo flags co = |
| 3546 | 3547 | | case conc of { CC_None -> False; _ -> True }
|
| 3547 | 3548 | -> return $ PuFail (cteProblem cteConcrete)
|
| 3548 | 3549 | |
| 3550 | +{- Trying NOT doing this -- #
|
|
| 3549 | 3551 | -- Check for coercion holes, if unifying.
|
| 3550 | 3552 | -- See (COERCION-HOLE) in Note [Unification preconditions]
|
| 3551 | 3553 | | case lc of { LC_None {} -> False; _ -> True } -- equivalent to "we are unifying"; see Note [TyEqFlags]
|
| 3552 | - , hasCoercionHoleCo co
|
|
| 3554 | + , hasHeteroKindCoercionHoleCo co
|
|
| 3553 | 3555 | -> return $ PuFail (cteProblem cteCoercionHole)
|
| 3556 | +-}
|
|
| 3554 | 3557 | |
| 3555 | 3558 | -- Occurs check (can promote)
|
| 3556 | 3559 | | OC_Check lhs_tv occ_prob <- occ
|
| 1 | +{-# LANGUAGE DuplicateRecordFields #-}
|
|
| 2 | + |
|
| 1 | 3 | {-
|
| 2 | 4 | (c) The University of Glasgow 2006
|
| 3 | 5 | (c) The AQUA Project, Glasgow University, 1996-1998
|
| ... | ... | @@ -36,6 +38,13 @@ module GHC.Tc.Zonk.TcType |
| 36 | 38 | -- ** Zonking constraints
|
| 37 | 39 | , zonkCt, zonkWC, zonkSimples, zonkImplication
|
| 38 | 40 | |
| 41 | + -- * Rewriter sets
|
|
| 42 | + , zonkRewriterSet, zonkCtRewriterSet, zonkCtEvRewriterSet
|
|
| 43 | + |
|
| 44 | + -- * Coercion holes
|
|
| 45 | + , isFilledCoercionHole, unpackCoercionHole, unpackCoercionHole_maybe
|
|
| 46 | + |
|
| 47 | + |
|
| 39 | 48 | -- * Tidying
|
| 40 | 49 | , tcInitTidyEnv, tcInitOpenTidyEnv
|
| 41 | 50 | , tidyCt, tidyEvVar, tidyDelayedError
|
| ... | ... | @@ -81,7 +90,7 @@ import GHC.Core.Coercion |
| 81 | 90 | import GHC.Core.Predicate
|
| 82 | 91 | |
| 83 | 92 | import GHC.Utils.Constants
|
| 84 | -import GHC.Utils.Outputable
|
|
| 93 | +import GHC.Utils.Outputable as Outputable
|
|
| 85 | 94 | import GHC.Utils.Misc
|
| 86 | 95 | import GHC.Utils.Monad ( mapAccumLM )
|
| 87 | 96 | import GHC.Utils.Panic
|
| ... | ... | @@ -89,6 +98,9 @@ import GHC.Utils.Panic |
| 89 | 98 | import GHC.Data.Bag
|
| 90 | 99 | import GHC.Data.Pair
|
| 91 | 100 | |
| 101 | +import Data.Semigroup
|
|
| 102 | +import Data.Maybe
|
|
| 103 | + |
|
| 92 | 104 | {- *********************************************************************
|
| 93 | 105 | * *
|
| 94 | 106 | Writing to metavariables
|
| ... | ... | @@ -366,8 +378,8 @@ checkCoercionHole cv co |
| 366 | 378 | ; return $
|
| 367 | 379 | assertPpr (ok cv_ty)
|
| 368 | 380 | (text "Bad coercion hole" <+>
|
| 369 | - ppr cv <> colon <+> vcat [ ppr t1, ppr t2, ppr role
|
|
| 370 | - , ppr cv_ty ])
|
|
| 381 | + ppr cv Outputable.<> colon
|
|
| 382 | + <+> vcat [ ppr t1, ppr t2, ppr role, ppr cv_ty ])
|
|
| 371 | 383 | co }
|
| 372 | 384 | | otherwise
|
| 373 | 385 | = return co
|
| ... | ... | @@ -494,9 +506,15 @@ zonkCt ct |
| 494 | 506 | ; return (mkNonCanonical fl') }
|
| 495 | 507 | |
| 496 | 508 | zonkCtEvidence :: CtEvidence -> ZonkM CtEvidence
|
| 497 | -zonkCtEvidence ctev
|
|
| 498 | - = do { pred' <- zonkTcType (ctEvPred ctev)
|
|
| 499 | - ; return (setCtEvPredType ctev pred') }
|
|
| 509 | +-- Zonks the ctev_pred and the ctev_rewriters; but not ctev_evar
|
|
| 510 | +-- For ctev_rewriters, see (WRW2) in Note [Wanteds rewrite Wanteds]
|
|
| 511 | +zonkCtEvidence (CtGiven (GivenCt { ctev_pred = pred, ctev_evar = var, ctev_loc = loc }))
|
|
| 512 | + = do { pred' <- zonkTcType pred
|
|
| 513 | + ; return (CtGiven (GivenCt { ctev_pred = pred', ctev_evar = var, ctev_loc = loc })) }
|
|
| 514 | +zonkCtEvidence (CtWanted wanted@(WantedCt { ctev_pred = pred, ctev_rewriters = rws }))
|
|
| 515 | + = do { pred' <- zonkTcType pred
|
|
| 516 | + ; rws' <- zonkRewriterSet rws
|
|
| 517 | + ; return (CtWanted (wanted { ctev_pred = pred', ctev_rewriters = rws' })) }
|
|
| 500 | 518 | |
| 501 | 519 | zonkSkolemInfo :: SkolemInfo -> ZonkM SkolemInfo
|
| 502 | 520 | zonkSkolemInfo (SkolemInfo u sk) = SkolemInfo u <$> zonkSkolemInfoAnon sk
|
| ... | ... | @@ -530,6 +548,103 @@ win. |
| 530 | 548 | |
| 531 | 549 | But c.f Note [Sharing when zonking to Type] in GHC.Tc.Zonk.Type.
|
| 532 | 550 | |
| 551 | +%************************************************************************
|
|
| 552 | +%* *
|
|
| 553 | + Zonking rewriter sets
|
|
| 554 | +* *
|
|
| 555 | +************************************************************************
|
|
| 556 | +-}
|
|
| 557 | + |
|
| 558 | +zonkCtRewriterSet :: Ct -> ZonkM Ct
|
|
| 559 | +zonkCtRewriterSet ct
|
|
| 560 | + | isGivenCt ct
|
|
| 561 | + = return ct
|
|
| 562 | + | otherwise
|
|
| 563 | + = case ct of
|
|
| 564 | + CEqCan eq@(EqCt { eq_ev = ev }) -> do { ev' <- zonkCtEvRewriterSet ev
|
|
| 565 | + ; return (CEqCan (eq { eq_ev = ev' })) }
|
|
| 566 | + CIrredCan ir@(IrredCt { ir_ev = ev }) -> do { ev' <- zonkCtEvRewriterSet ev
|
|
| 567 | + ; return (CIrredCan (ir { ir_ev = ev' })) }
|
|
| 568 | + CDictCan di@(DictCt { di_ev = ev }) -> do { ev' <- zonkCtEvRewriterSet ev
|
|
| 569 | + ; return (CDictCan (di { di_ev = ev' })) }
|
|
| 570 | + CQuantCan {} -> return ct
|
|
| 571 | + CNonCanonical ev -> do { ev' <- zonkCtEvRewriterSet ev
|
|
| 572 | + ; return (CNonCanonical ev') }
|
|
| 573 | + |
|
| 574 | +zonkCtEvRewriterSet :: CtEvidence -> ZonkM CtEvidence
|
|
| 575 | +zonkCtEvRewriterSet ev@(CtGiven {})
|
|
| 576 | + = return ev
|
|
| 577 | +zonkCtEvRewriterSet ev@(CtWanted wtd)
|
|
| 578 | + = do { rewriters' <- zonkRewriterSet (ctEvRewriters ev)
|
|
| 579 | + ; return (CtWanted $ setWantedCtEvRewriters wtd rewriters') }
|
|
| 580 | + |
|
| 581 | +-- | Zonk a rewriter set; if a coercion hole in the set has been filled,
|
|
| 582 | +-- find all the free un-filled coercion holes in the coercion that fills it
|
|
| 583 | +zonkRewriterSet :: RewriterSet -> ZonkM RewriterSet
|
|
| 584 | +zonkRewriterSet (RewriterSet set)
|
|
| 585 | + = nonDetStrictFoldUniqSet go (return emptyRewriterSet) set
|
|
| 586 | + -- This does not introduce non-determinism, because the only
|
|
| 587 | + -- monadic action is to read, and the combining function is
|
|
| 588 | + -- commutative
|
|
| 589 | + where
|
|
| 590 | + go :: CoercionHole -> ZonkM RewriterSet -> ZonkM RewriterSet
|
|
| 591 | + go hole m_acc = unionRewriterSet <$> check_hole hole <*> m_acc
|
|
| 592 | + |
|
| 593 | + check_hole :: CoercionHole -> ZonkM RewriterSet
|
|
| 594 | + check_hole hole
|
|
| 595 | + = do { m_co <- unpackCoercionHole_maybe hole
|
|
| 596 | + ; case m_co of
|
|
| 597 | + Nothing -> return (unitRewriterSet hole) -- Not filled
|
|
| 598 | + Just co -> unUCHM (check_co co) } -- Filled: look inside
|
|
| 599 | + |
|
| 600 | + check_ty :: Type -> UnfilledCoercionHoleMonoid
|
|
| 601 | + check_co :: Coercion -> UnfilledCoercionHoleMonoid
|
|
| 602 | + (check_ty, _, check_co, _) = foldTyCo folder ()
|
|
| 603 | + |
|
| 604 | + folder :: TyCoFolder () UnfilledCoercionHoleMonoid
|
|
| 605 | + folder = TyCoFolder { tcf_view = noView
|
|
| 606 | + , tcf_tyvar = \ _ tv -> check_ty (tyVarKind tv)
|
|
| 607 | + , tcf_covar = \ _ cv -> check_ty (varType cv)
|
|
| 608 | + , tcf_hole = \ _ -> UCHM . check_hole
|
|
| 609 | + , tcf_tycobinder = \ _ _ _ -> () }
|
|
| 610 | + |
|
| 611 | +newtype UnfilledCoercionHoleMonoid = UCHM { unUCHM :: ZonkM RewriterSet }
|
|
| 612 | + |
|
| 613 | +instance Semigroup UnfilledCoercionHoleMonoid where
|
|
| 614 | + UCHM l <> UCHM r = UCHM (unionRewriterSet <$> l <*> r)
|
|
| 615 | + |
|
| 616 | +instance Monoid UnfilledCoercionHoleMonoid where
|
|
| 617 | + mempty = UCHM (return emptyRewriterSet)
|
|
| 618 | + |
|
| 619 | + |
|
| 620 | +{-
|
|
| 621 | +************************************************************************
|
|
| 622 | +* *
|
|
| 623 | + Checking for coercion holes
|
|
| 624 | +* *
|
|
| 625 | +************************************************************************
|
|
| 626 | +-}
|
|
| 627 | + |
|
| 628 | +-- | Is a coercion hole filled in?
|
|
| 629 | +isFilledCoercionHole :: CoercionHole -> ZonkM Bool
|
|
| 630 | +isFilledCoercionHole (CoercionHole { ch_ref = ref })
|
|
| 631 | + = isJust <$> readTcRef ref
|
|
| 632 | + |
|
| 633 | +-- | Retrieve the contents of a coercion hole. Panics if the hole
|
|
| 634 | +-- is unfilled
|
|
| 635 | +unpackCoercionHole :: CoercionHole -> ZonkM Coercion
|
|
| 636 | +unpackCoercionHole hole
|
|
| 637 | + = do { contents <- unpackCoercionHole_maybe hole
|
|
| 638 | + ; case contents of
|
|
| 639 | + Just co -> return co
|
|
| 640 | + Nothing -> pprPanic "Unfilled coercion hole" (ppr hole) }
|
|
| 641 | + |
|
| 642 | +-- | Retrieve the contents of a coercion hole, if it is filled
|
|
| 643 | +unpackCoercionHole_maybe :: CoercionHole -> ZonkM (Maybe Coercion)
|
|
| 644 | +unpackCoercionHole_maybe (CoercionHole { ch_ref = ref }) = readTcRef ref
|
|
| 645 | + |
|
| 646 | + |
|
| 647 | +{-
|
|
| 533 | 648 | %************************************************************************
|
| 534 | 649 | %* *
|
| 535 | 650 | Tidying
|
| ... | ... | @@ -28,12 +28,6 @@ module GHC.Tc.Zonk.Type ( |
| 28 | 28 | -- ** 'ZonkEnv', and the 'ZonkT' and 'ZonkBndrT' monad transformers
|
| 29 | 29 | module GHC.Tc.Zonk.Env,
|
| 30 | 30 | |
| 31 | - -- * Coercion holes
|
|
| 32 | - isFilledCoercionHole, unpackCoercionHole, unpackCoercionHole_maybe,
|
|
| 33 | - |
|
| 34 | - -- * Rewriter sets
|
|
| 35 | - zonkRewriterSet, zonkCtRewriterSet, zonkCtEvRewriterSet,
|
|
| 36 | - |
|
| 37 | 31 | -- * Tidying
|
| 38 | 32 | tcInitTidyEnv, tcInitOpenTidyEnv,
|
| 39 | 33 | |
| ... | ... | @@ -55,7 +49,6 @@ import GHC.Tc.TyCl.Build ( TcMethInfo, MethInfo ) |
| 55 | 49 | import GHC.Tc.Utils.Env ( tcLookupGlobalOnly )
|
| 56 | 50 | import GHC.Tc.Utils.TcType
|
| 57 | 51 | import GHC.Tc.Utils.Monad ( newZonkAnyType, setSrcSpanA, liftZonkM, traceTc, addErr )
|
| 58 | -import GHC.Tc.Types.Constraint
|
|
| 59 | 52 | import GHC.Tc.Types.Evidence
|
| 60 | 53 | import GHC.Tc.Errors.Types
|
| 61 | 54 | import GHC.Tc.Zonk.Env
|
| ... | ... | @@ -88,7 +81,6 @@ import GHC.Types.Id |
| 88 | 81 | import GHC.Types.TypeEnv
|
| 89 | 82 | import GHC.Types.Basic
|
| 90 | 83 | import GHC.Types.SrcLoc
|
| 91 | -import GHC.Types.Unique.Set
|
|
| 92 | 84 | import GHC.Types.Unique.FM
|
| 93 | 85 | import GHC.Types.TyThing
|
| 94 | 86 | |
| ... | ... | @@ -99,7 +91,6 @@ import GHC.Data.Bag |
| 99 | 91 | |
| 100 | 92 | import Control.Monad
|
| 101 | 93 | import Control.Monad.Trans.Class ( lift )
|
| 102 | -import Data.Semigroup
|
|
| 103 | 94 | import Data.List.NonEmpty ( NonEmpty )
|
| 104 | 95 | import Data.Foldable ( toList )
|
| 105 | 96 | |
| ... | ... | @@ -1956,89 +1947,3 @@ finding the free type vars of an expression is necessarily monadic |
| 1956 | 1947 | operation. (consider /\a -> f @ b, where b is side-effected to a)
|
| 1957 | 1948 | -}
|
| 1958 | 1949 | |
| 1959 | -{-
|
|
| 1960 | -************************************************************************
|
|
| 1961 | -* *
|
|
| 1962 | - Checking for coercion holes
|
|
| 1963 | -* *
|
|
| 1964 | -************************************************************************
|
|
| 1965 | --}
|
|
| 1966 | - |
|
| 1967 | --- | Is a coercion hole filled in?
|
|
| 1968 | -isFilledCoercionHole :: CoercionHole -> TcM Bool
|
|
| 1969 | -isFilledCoercionHole (CoercionHole { ch_ref = ref })
|
|
| 1970 | - = isJust <$> readTcRef ref
|
|
| 1971 | - |
|
| 1972 | --- | Retrieve the contents of a coercion hole. Panics if the hole
|
|
| 1973 | --- is unfilled
|
|
| 1974 | -unpackCoercionHole :: CoercionHole -> TcM Coercion
|
|
| 1975 | -unpackCoercionHole hole
|
|
| 1976 | - = do { contents <- unpackCoercionHole_maybe hole
|
|
| 1977 | - ; case contents of
|
|
| 1978 | - Just co -> return co
|
|
| 1979 | - Nothing -> pprPanic "Unfilled coercion hole" (ppr hole) }
|
|
| 1980 | - |
|
| 1981 | --- | Retrieve the contents of a coercion hole, if it is filled
|
|
| 1982 | -unpackCoercionHole_maybe :: CoercionHole -> TcM (Maybe Coercion)
|
|
| 1983 | -unpackCoercionHole_maybe (CoercionHole { ch_ref = ref }) = readTcRef ref
|
|
| 1984 | - |
|
| 1985 | -zonkCtRewriterSet :: Ct -> TcM Ct
|
|
| 1986 | -zonkCtRewriterSet ct
|
|
| 1987 | - | isGivenCt ct
|
|
| 1988 | - = return ct
|
|
| 1989 | - | otherwise
|
|
| 1990 | - = case ct of
|
|
| 1991 | - CEqCan eq@(EqCt { eq_ev = ev }) -> do { ev' <- zonkCtEvRewriterSet ev
|
|
| 1992 | - ; return (CEqCan (eq { eq_ev = ev' })) }
|
|
| 1993 | - CIrredCan ir@(IrredCt { ir_ev = ev }) -> do { ev' <- zonkCtEvRewriterSet ev
|
|
| 1994 | - ; return (CIrredCan (ir { ir_ev = ev' })) }
|
|
| 1995 | - CDictCan di@(DictCt { di_ev = ev }) -> do { ev' <- zonkCtEvRewriterSet ev
|
|
| 1996 | - ; return (CDictCan (di { di_ev = ev' })) }
|
|
| 1997 | - CQuantCan {} -> return ct
|
|
| 1998 | - CNonCanonical ev -> do { ev' <- zonkCtEvRewriterSet ev
|
|
| 1999 | - ; return (CNonCanonical ev') }
|
|
| 2000 | - |
|
| 2001 | -zonkCtEvRewriterSet :: CtEvidence -> TcM CtEvidence
|
|
| 2002 | -zonkCtEvRewriterSet ev@(CtGiven {})
|
|
| 2003 | - = return ev
|
|
| 2004 | -zonkCtEvRewriterSet ev@(CtWanted wtd)
|
|
| 2005 | - = do { rewriters' <- zonkRewriterSet (ctEvRewriters ev)
|
|
| 2006 | - ; return (CtWanted $ setWantedCtEvRewriters wtd rewriters') }
|
|
| 2007 | - |
|
| 2008 | --- | Check whether any coercion hole in a RewriterSet is still unsolved.
|
|
| 2009 | --- Does this by recursively looking through filled coercion holes until
|
|
| 2010 | --- one is found that is not yet filled in, at which point this aborts.
|
|
| 2011 | -zonkRewriterSet :: RewriterSet -> TcM RewriterSet
|
|
| 2012 | -zonkRewriterSet (RewriterSet set)
|
|
| 2013 | - = nonDetStrictFoldUniqSet go (return emptyRewriterSet) set
|
|
| 2014 | - -- this does not introduce non-determinism, because the only
|
|
| 2015 | - -- monadic action is to read, and the combining function is
|
|
| 2016 | - -- commutative
|
|
| 2017 | - where
|
|
| 2018 | - go :: CoercionHole -> TcM RewriterSet -> TcM RewriterSet
|
|
| 2019 | - go hole m_acc = unionRewriterSet <$> check_hole hole <*> m_acc
|
|
| 2020 | - |
|
| 2021 | - check_hole :: CoercionHole -> TcM RewriterSet
|
|
| 2022 | - check_hole hole = do { m_co <- unpackCoercionHole_maybe hole
|
|
| 2023 | - ; case m_co of
|
|
| 2024 | - Nothing -> return (unitRewriterSet hole)
|
|
| 2025 | - Just co -> unUCHM (check_co co) }
|
|
| 2026 | - |
|
| 2027 | - check_ty :: Type -> UnfilledCoercionHoleMonoid
|
|
| 2028 | - check_co :: Coercion -> UnfilledCoercionHoleMonoid
|
|
| 2029 | - (check_ty, _, check_co, _) = foldTyCo folder ()
|
|
| 2030 | - |
|
| 2031 | - folder :: TyCoFolder () UnfilledCoercionHoleMonoid
|
|
| 2032 | - folder = TyCoFolder { tcf_view = noView
|
|
| 2033 | - , tcf_tyvar = \ _ tv -> check_ty (tyVarKind tv)
|
|
| 2034 | - , tcf_covar = \ _ cv -> check_ty (varType cv)
|
|
| 2035 | - , tcf_hole = \ _ -> UCHM . check_hole
|
|
| 2036 | - , tcf_tycobinder = \ _ _ _ -> () }
|
|
| 2037 | - |
|
| 2038 | -newtype UnfilledCoercionHoleMonoid = UCHM { unUCHM :: TcM RewriterSet }
|
|
| 2039 | - |
|
| 2040 | -instance Semigroup UnfilledCoercionHoleMonoid where
|
|
| 2041 | - UCHM l <> UCHM r = UCHM (unionRewriterSet <$> l <*> r)
|
|
| 2042 | - |
|
| 2043 | -instance Monoid UnfilledCoercionHoleMonoid where
|
|
| 2044 | - mempty = UCHM (return emptyRewriterSet) |
| ... | ... | @@ -87,7 +87,7 @@ module GHC.Types.Basic ( |
| 87 | 87 | CompilerPhase(..), PhaseNum, beginPhase, nextPhase, laterPhase,
|
| 88 | 88 | |
| 89 | 89 | Activation(..), isActive, competesWith,
|
| 90 | - isNeverActive, isAlwaysActive, activeInFinalPhase,
|
|
| 90 | + isNeverActive, isAlwaysActive, activeInFinalPhase, activeInInitialPhase,
|
|
| 91 | 91 | activateAfterInitial, activateDuringFinal, activeAfter,
|
| 92 | 92 | |
| 93 | 93 | RuleMatchInfo(..), isConLike, isFunLike,
|
| 1 | - |
|
| 2 | -T3330c.hs:25:43: error: [GHC-18872]
|
|
| 3 | - • Couldn't match kind ‘* -> *’ with ‘*’
|
|
| 4 | - When matching types
|
|
| 5 | - f1 :: * -> *
|
|
| 6 | - f1 x :: *
|
|
| 7 | - Expected: Der ((->) x) (Der f1 x)
|
|
| 8 | - Actual: R f1
|
|
| 9 | - • In the first argument of ‘plug’, namely ‘rf’
|
|
| 1 | +T3330c.hs:25:38: error: [GHC-25897]
|
|
| 2 | + • Could not deduce ‘Der f1 ~ f1’
|
|
| 3 | + from the context: f ~ (f1 :+: g)
|
|
| 4 | + bound by a pattern with constructor:
|
|
| 5 | + RSum :: forall (f :: * -> *) (g :: * -> *).
|
|
| 6 | + R f -> R g -> R (f :+: g),
|
|
| 7 | + in an equation for ‘plug'’
|
|
| 8 | + at T3330c.hs:25:8-17
|
|
| 9 | + Expected: x -> f1 x
|
|
| 10 | + Actual: x -> Der f1 x
|
|
| 11 | + ‘f1’ is a rigid type variable bound by
|
|
| 12 | + a pattern with constructor:
|
|
| 13 | + RSum :: forall (f :: * -> *) (g :: * -> *).
|
|
| 14 | + R f -> R g -> R (f :+: g),
|
|
| 15 | + in an equation for ‘plug'’
|
|
| 16 | + at T3330c.hs:25:8-17
|
|
| 17 | + • The function ‘plug’ is applied to three visible arguments,
|
|
| 18 | + but its type ‘Rep f => Der f x -> x -> f x’ has only two
|
|
| 10 | 19 | In the first argument of ‘Inl’, namely ‘(plug rf df x)’
|
| 11 | 20 | In the expression: Inl (plug rf df x)
|
| 12 | 21 | • Relevant bindings include
|
| 13 | - x :: x (bound at T3330c.hs:25:29)
|
|
| 14 | 22 | df :: Der f1 x (bound at T3330c.hs:25:25)
|
| 15 | 23 | rf :: R f1 (bound at T3330c.hs:25:13)
|
| 16 | - plug' :: R f -> Der f x -> x -> f x (bound at T3330c.hs:25:1) |
|
| 24 | + |
| 1 | - |
|
| 2 | -T4174.hs:45:12: error: [GHC-18872]
|
|
| 3 | - • Couldn't match type ‘False’ with ‘True’
|
|
| 4 | - arising from a use of ‘sync_large_objects’
|
|
| 1 | +T4174.hs:45:12: error: [GHC-25897]
|
|
| 2 | + • Couldn't match type ‘a’ with ‘SmStep’
|
|
| 3 | + Expected: m (Field (Way (GHC6'8 minor) n t p) a b)
|
|
| 4 | + Actual: m (Field (WayOf m) SmStep RtsSpinLock)
|
|
| 5 | + ‘a’ is a rigid type variable bound by
|
|
| 6 | + the type signature for:
|
|
| 7 | + testcase :: forall (m :: * -> *) minor n t p a b.
|
|
| 8 | + Monad m =>
|
|
| 9 | + m (Field (Way (GHC6'8 minor) n t p) a b)
|
|
| 10 | + at T4174.hs:44:1-63
|
|
| 5 | 11 | • In the expression: sync_large_objects
|
| 6 | 12 | In an equation for ‘testcase’: testcase = sync_large_objects
|
| 13 | + • Relevant bindings include
|
|
| 14 | + testcase :: m (Field (Way (GHC6'8 minor) n t p) a b)
|
|
| 15 | + (bound at T4174.hs:45:1)
|
|
| 16 | + |
| ... | ... | @@ -13,12 +13,3 @@ T8227.hs:24:27: error: [GHC-83865] |
| 13 | 13 | absoluteToParam :: Scalar (V a) -> a -> Scalar (V a)
|
| 14 | 14 | (bound at T8227.hs:24:1)
|
| 15 | 15 | |
| 16 | -T8227.hs:24:48: error: [GHC-27958]
|
|
| 17 | - • Couldn't match type ‘p0’ with ‘Scalar (V p0)’
|
|
| 18 | - arising from a type equality Scalar (V a) ~ Scalar (V p0) -> p0
|
|
| 19 | - The type variable ‘p0’ is ambiguous
|
|
| 20 | - • In the second argument of ‘arcLengthToParam’, namely ‘eps’
|
|
| 21 | - In the expression: arcLengthToParam eps eps
|
|
| 22 | - In an equation for ‘absoluteToParam’:
|
|
| 23 | - absoluteToParam eps seg = arcLengthToParam eps eps
|
|
| 24 | - |
| 1 | +module T25703 where
|
|
| 2 | + |
|
| 3 | +f :: (Eq a, Show b) => a -> b -> Int
|
|
| 4 | +f x y = f x y
|
|
| 5 | + |
|
| 6 | +goo :: forall x. (Eq x) => x -> Int
|
|
| 7 | +goo arg = f arg (3::Int) |
| 1 | +Rule fired: SPEC f @_ @Int (T25703)
|
|
| 2 | +Rule fired: SPEC f @_ @Int (T25703) |
| 1 | +{-# LANGUAGE DataKinds #-}
|
|
| 2 | +{-# LANGUAGE GADTs #-}
|
|
| 3 | + |
|
| 4 | +{-# OPTIONS_GHC -O2 -fspecialise-aggressively #-}
|
|
| 5 | + |
|
| 6 | +-- This pragma is just here to pretend that the function body of 'foo' is huge
|
|
| 7 | +-- and should never be inlined.
|
|
| 8 | +{-# OPTIONS_GHC -funfolding-use-threshold=-200 #-}
|
|
| 9 | + |
|
| 10 | +module T25703a where
|
|
| 11 | + |
|
| 12 | +import Data.Kind
|
|
| 13 | +import Data.Type.Equality
|
|
| 14 | +import Data.Proxy
|
|
| 15 | +import GHC.TypeNats
|
|
| 16 | + |
|
| 17 | +-- Pretend this is some big dictionary that absolutely must get
|
|
| 18 | +-- specialised away for performance reasons.
|
|
| 19 | +type C :: Nat -> Constraint
|
|
| 20 | +class C i where
|
|
| 21 | + meth :: Proxy i -> Double
|
|
| 22 | +instance C 0 where
|
|
| 23 | + meth _ = 0.1
|
|
| 24 | +instance C 1 where
|
|
| 25 | + meth _ = 1.1
|
|
| 26 | +instance C 2 where
|
|
| 27 | + meth _ = 2.1
|
|
| 28 | + |
|
| 29 | +{-# INLINEABLE foo #-}
|
|
| 30 | +foo :: forall a (n :: Nat) (m :: Nat)
|
|
| 31 | + . ( Eq a, C n, C m )
|
|
| 32 | + => a -> ( Proxy n, Proxy m ) -> Int -> Double
|
|
| 33 | +-- Pretend this is a big complicated function, too big to inline,
|
|
| 34 | +-- for which we absolutely must specialise away the 'C n', 'C m'
|
|
| 35 | +-- dictionaries for performance reasons.
|
|
| 36 | +foo a b c
|
|
| 37 | + = if a == a
|
|
| 38 | + then meth @n Proxy + fromIntegral c
|
|
| 39 | + else 2 * meth @m Proxy
|
|
| 40 | + |
|
| 41 | +-- Runtime dispatch to a specialisation of 'foo'
|
|
| 42 | +foo_spec :: forall a (n :: Nat) (m :: Nat)
|
|
| 43 | + . ( Eq a, KnownNat n, KnownNat m )
|
|
| 44 | + => a -> ( Proxy n, Proxy m ) -> Int -> Double
|
|
| 45 | +foo_spec a b c
|
|
| 46 | + | Just Refl <- sameNat @n @0 Proxy Proxy
|
|
| 47 | + , Just Refl <- sameNat @m @0 Proxy Proxy
|
|
| 48 | + = foo @a @0 @0 a b c
|
|
| 49 | + | Just Refl <- sameNat @n @0 Proxy Proxy
|
|
| 50 | + , Just Refl <- sameNat @m @1 Proxy Proxy
|
|
| 51 | + = foo @a @0 @1 a b c
|
|
| 52 | + | Just Refl <- sameNat @n @1 Proxy Proxy
|
|
| 53 | + , Just Refl <- sameNat @m @1 Proxy Proxy
|
|
| 54 | + = foo @a @1 @1 a b c
|
|
| 55 | + | Just Refl <- sameNat @n @0 Proxy Proxy
|
|
| 56 | + , Just Refl <- sameNat @m @2 Proxy Proxy
|
|
| 57 | + = foo @a @0 @2 a b c
|
|
| 58 | + | Just Refl <- sameNat @n @1 Proxy Proxy
|
|
| 59 | + , Just Refl <- sameNat @m @2 Proxy Proxy
|
|
| 60 | + = foo @a @1 @2 a b c
|
|
| 61 | + | Just Refl <- sameNat @n @2 Proxy Proxy
|
|
| 62 | + , Just Refl <- sameNat @m @2 Proxy Proxy
|
|
| 63 | + = foo @a @2 @2 a b c
|
|
| 64 | + | otherwise
|
|
| 65 | + = error $ unlines
|
|
| 66 | + [ "f: no specialisation"
|
|
| 67 | + , "n: " ++ show (natVal @n Proxy)
|
|
| 68 | + , "m: " ++ show (natVal @m Proxy)
|
|
| 69 | + ] |
| 1 | +Rule fired: SPEC foo @_ @2 @2 (T25703a)
|
|
| 2 | +Rule fired: SPEC foo @_ @1 @2 (T25703a)
|
|
| 3 | +Rule fired: SPEC foo @_ @0 @2 (T25703a)
|
|
| 4 | +Rule fired: SPEC foo @_ @1 @1 (T25703a)
|
|
| 5 | +Rule fired: SPEC foo @_ @0 @1 (T25703a)
|
|
| 6 | +Rule fired: SPEC foo @_ @0 @0 (T25703a) |
| 1 | +{-# LANGUAGE TypeFamilies #-}
|
|
| 2 | +{-# OPTIONS_GHC -O -fpolymorphic-specialisation #-}
|
|
| 3 | + |
|
| 4 | +module Foo where
|
|
| 5 | + |
|
| 6 | +type family F a
|
|
| 7 | + |
|
| 8 | +data T a = T1
|
|
| 9 | + |
|
| 10 | +instance Eq (T a) where { (==) x y = False }
|
|
| 11 | + |
|
| 12 | +foo :: Eq a => a -> Bool
|
|
| 13 | +foo x | x==x = True
|
|
| 14 | + | otherwise = foo x
|
|
| 15 | + |
|
| 16 | +bar :: forall b. b -> T (F b) -> Bool
|
|
| 17 | +bar y x = foo x
|
|
| 18 | + |
| ... | ... | @@ -543,3 +543,8 @@ test('T25883c', normal, compile_grep_core, ['']) |
| 543 | 543 | test('T25883d', [extra_files(['T25883d_import.hs'])], multimod_compile_filter, ['T25883d', '-O -ddump-simpl -dno-typeable-binds -dsuppress-all -dsuppress-uniques', r'grep -e "y ="'])
|
| 544 | 544 | |
| 545 | 545 | test('T25976', [grep_errmsg('Dead Code')], compile, ['-O -ddump-simpl -dsuppress-uniques -dno-typeable-binds'])
|
| 546 | + |
|
| 547 | +test('T25965', normal, compile, ['-O'])
|
|
| 548 | +test('T25703', [grep_errmsg(r'SPEC')], compile, ['-O -fpolymorphic-specialisation -ddump-rule-firings'])
|
|
| 549 | +test('T25703a', [grep_errmsg(r'SPEC')], compile, ['-O -fpolymorphic-specialisation -ddump-rule-firings'])
|
|
| 550 | + |
| 1 | -T25266a.hs:10:41: error: [GHC-25897]
|
|
| 2 | - • Could not deduce ‘p1 ~ p2’
|
|
| 1 | +T25266a.hs:10:39: error: [GHC-25897]
|
|
| 2 | + • Could not deduce ‘p2 ~ p1’
|
|
| 3 | 3 | from the context: a ~ Int
|
| 4 | 4 | bound by a pattern with constructor: T1 :: T Int,
|
| 5 | 5 | in a case alternative
|
| 6 | 6 | at T25266a.hs:10:23-24
|
| 7 | - ‘p1’ is a rigid type variable bound by
|
|
| 7 | + ‘p2’ is a rigid type variable bound by
|
|
| 8 | 8 | the inferred type of f :: p1 -> p2 -> T a -> Int
|
| 9 | 9 | at T25266a.hs:(9,1)-(11,40)
|
| 10 | - ‘p2’ is a rigid type variable bound by
|
|
| 10 | + ‘p1’ is a rigid type variable bound by
|
|
| 11 | 11 | the inferred type of f :: p1 -> p2 -> T a -> Int
|
| 12 | 12 | at T25266a.hs:(9,1)-(11,40)
|
| 13 | - • In the expression: y
|
|
| 13 | + • In the expression: x
|
|
| 14 | 14 | In the first argument of ‘length’, namely ‘[x, y]’
|
| 15 | 15 | In the expression: length [x, y]
|
| 16 | 16 | • Relevant bindings include
|
| 1 | - |
|
| 2 | 1 | T18851.hs:35:5: error: [GHC-18872]
|
| 3 | - • Couldn't match type ‘B’ with ‘A’
|
|
| 4 | - arising from a superclass required to satisfy ‘C int0 A’,
|
|
| 2 | + • Couldn't match type ‘Bool’ with ‘B’
|
|
| 3 | + arising from a superclass required to satisfy ‘C Int B’,
|
|
| 5 | 4 | arising from a use of ‘f’
|
| 6 | 5 | • In the expression: f @A @B
|
| 7 | 6 | In an equation for ‘g’: g = f @A @B
|
| 7 | + |