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 | + |