Simon Peyton Jones pushed to branch wip/T26582 at Glasgow Haskell Compiler / GHC
Commits:
-
5851a7c1
by Simon Peyton Jones at 2025-11-17T10:26:20+00:00
6 changed files:
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/Utils/TcType.hs
- + testsuite/tests/typecheck/should_compile/T26582.hs
- testsuite/tests/typecheck/should_compile/all.T
Changes:
| ... | ... | @@ -395,9 +395,11 @@ tryConstraintDefaulting wc |
| 395 | 395 | | isEmptyWC wc
|
| 396 | 396 | = return wc
|
| 397 | 397 | | otherwise
|
| 398 | - = do { (unif_happened, better_wc) <- reportCoarseGrainUnifications $
|
|
| 399 | - go_wc False wc
|
|
| 400 | - -- We may have done unifications; so solve again
|
|
| 398 | + = do { (outermost_unif_lvl, better_wc) <- reportCoarseGrainUnifications $
|
|
| 399 | + go_wc False wc
|
|
| 400 | + |
|
| 401 | + -- We may have done unifications; if so, solve again
|
|
| 402 | + ; let unif_happened = not (isInfiniteTcLevel outermost_unif_lvl)
|
|
| 401 | 403 | ; solveAgainIf unif_happened better_wc }
|
| 402 | 404 | where
|
| 403 | 405 | go_wc :: Bool -> WantedConstraints -> TcS WantedConstraints
|
| ... | ... | @@ -414,14 +416,17 @@ tryConstraintDefaulting wc |
| 414 | 416 | else return (Just ct) }
|
| 415 | 417 | |
| 416 | 418 | go_implic :: Bool -> Implication -> TcS Implication
|
| 417 | - go_implic encl_eqs implic@(Implic { ic_status = status, ic_wanted = wanteds
|
|
| 418 | - , ic_given_eqs = given_eqs, ic_binds = binds })
|
|
| 419 | + go_implic encl_eqs implic@(Implic { ic_tclvl = tclvl
|
|
| 420 | + , ic_status = status, ic_wanted = wanteds
|
|
| 421 | + , ic_given_eqs = given_eqs, ic_binds = binds })
|
|
| 419 | 422 | | isSolvedStatus status
|
| 420 | 423 | = return implic -- Nothing to solve inside here
|
| 421 | 424 | | otherwise
|
| 422 | 425 | = do { let encl_eqs' = encl_eqs || given_eqs /= NoGivenEqs
|
| 423 | 426 | |
| 424 | - ; wanteds' <- setEvBindsTcS binds $
|
|
| 427 | + ; wanteds' <- setTcLevelTcS tclvl $
|
|
| 428 | + -- Set the levels so that reportCoareseGrainUnifications works
|
|
| 429 | + setEvBindsTcS binds $
|
|
| 425 | 430 | -- defaultCallStack sets a binding, so
|
| 426 | 431 | -- we must set the correct binding group
|
| 427 | 432 | go_wc encl_eqs' wanteds
|
| ... | ... | @@ -660,7 +665,9 @@ Wrinkles: |
| 660 | 665 | f x = case x of T1 -> True
|
| 661 | 666 | |
| 662 | 667 | Should we infer f :: T a -> Bool, or f :: T a -> a. Both are valid, but
|
| 663 | - neither is more general than the other.
|
|
| 668 | + neither is more general than the other. But by the time defaulting takes
|
|
| 669 | + place all let-bound variables have got their final types; defaulting won't
|
|
| 670 | + affect let-generalisation.
|
|
| 664 | 671 | |
| 665 | 672 | (DE2) We still can't unify if there is a skolem-escape check, or an occurs check,
|
| 666 | 673 | or it it'd mean unifying a TyVarTv with a non-tyvar. It's only the
|
| ... | ... | @@ -1877,18 +1877,18 @@ reportFineGrainUnifications (TcS thing_inside) |
| 1877 | 1877 | ; recordUnifications outer_wu unif_tvs
|
| 1878 | 1878 | ; return (unif_tvs, res) }
|
| 1879 | 1879 | |
| 1880 | -reportCoarseGrainUnifications :: TcS a -> TcS (Bool, a)
|
|
| 1880 | +reportCoarseGrainUnifications :: TcS a -> TcS (TcLevel, a)
|
|
| 1881 | 1881 | -- Record whether any useful unifications are done by thing_inside
|
| 1882 | +-- Specifically: return the TcLevel of the outermost (smallest level)
|
|
| 1883 | +-- unification variable that has been unified, or infiniteTcLevel if none
|
|
| 1882 | 1884 | -- Remember to propagate the information to the enclosing context
|
| 1883 | 1885 | reportCoarseGrainUnifications (TcS thing_inside)
|
| 1884 | 1886 | = TcS $ \ env@(TcSEnv { tcs_what = outer_what }) ->
|
| 1885 | 1887 | case outer_what of
|
| 1886 | - WU_None
|
|
| 1887 | - -> do { (unif_happened, _, res) <- report_coarse_grain_unifs env thing_inside
|
|
| 1888 | - ; return (unif_happened, res) }
|
|
| 1888 | + WU_None -> report_coarse_grain_unifs env thing_inside
|
|
| 1889 | 1889 | |
| 1890 | 1890 | WU_Coarse outer_ul_ref
|
| 1891 | - -> do { (unif_happened, inner_ul, res) <- report_coarse_grain_unifs env thing_inside
|
|
| 1891 | + -> do { (inner_ul, res) <- report_coarse_grain_unifs env thing_inside
|
|
| 1892 | 1892 | |
| 1893 | 1893 | -- Propagate to outer_ul_ref
|
| 1894 | 1894 | ; outer_ul <- TcM.readTcRef outer_ul_ref
|
| ... | ... | @@ -1897,31 +1897,32 @@ reportCoarseGrainUnifications (TcS thing_inside) |
| 1897 | 1897 | |
| 1898 | 1898 | ; TcM.traceTc "reportCoarse(Coarse)" $
|
| 1899 | 1899 | vcat [ text "outer_ul" <+> ppr outer_ul
|
| 1900 | - , text "inner_ul" <+> ppr inner_ul
|
|
| 1901 | - , text "unif_happened" <+> ppr unif_happened ]
|
|
| 1902 | - ; return (unif_happened, res) }
|
|
| 1900 | + , text "inner_ul" <+> ppr inner_ul]
|
|
| 1901 | + ; return (inner_ul, res) }
|
|
| 1903 | 1902 | |
| 1904 | 1903 | WU_Fine outer_tvs_ref
|
| 1905 | 1904 | -> do { (unif_tvs,res) <- report_fine_grain_unifs env thing_inside
|
| 1906 | - ; let unif_happened = not (isEmptyVarSet unif_tvs)
|
|
| 1907 | - ; when unif_happened $
|
|
| 1908 | - TcM.updTcRef outer_tvs_ref (`unionVarSet` unif_tvs)
|
|
| 1905 | + |
|
| 1906 | + -- Propagate to outer_tvs_rev
|
|
| 1907 | + ; TcM.updTcRef outer_tvs_ref (`unionVarSet` unif_tvs)
|
|
| 1908 | + |
|
| 1909 | + ; let outermost_unif_lvl = minTcTyVarSetLevel unif_tvs
|
|
| 1909 | 1910 | ; TcM.traceTc "reportCoarse(Fine)" $
|
| 1910 | 1911 | vcat [ text "unif_tvs" <+> ppr unif_tvs
|
| 1911 | - , text "unif_happened" <+> ppr unif_happened ]
|
|
| 1912 | - ; return (unif_happened, res) }
|
|
| 1912 | + , text "unif_happened" <+> ppr outermost_unif_lvl ]
|
|
| 1913 | + ; return (outermost_unif_lvl, res) }
|
|
| 1913 | 1914 | |
| 1914 | 1915 | report_coarse_grain_unifs :: TcSEnv -> (TcSEnv -> TcM a)
|
| 1915 | - -> TcM (Bool, TcLevel, a)
|
|
| 1916 | --- Returns (unif_happened, coarse_inner_ul, res)
|
|
| 1916 | + -> TcM (TcLevel, a)
|
|
| 1917 | +-- Returns the level number of the outermost
|
|
| 1918 | +-- unification variable that is unified
|
|
| 1917 | 1919 | report_coarse_grain_unifs env thing_inside
|
| 1918 | 1920 | = do { inner_ul_ref <- TcM.newTcRef infiniteTcLevel
|
| 1919 | 1921 | ; res <- thing_inside (env { tcs_what = WU_Coarse inner_ul_ref })
|
| 1920 | - ; inner_ul <- TcM.readTcRef inner_ul_ref
|
|
| 1921 | - ; ambient_lvl <- TcM.getTcLevel
|
|
| 1922 | - ; let unif_happened = ambient_lvl `deeperThanOrSame` inner_ul
|
|
| 1923 | - ; return (unif_happened, inner_ul, res) }
|
|
| 1924 | - |
|
| 1922 | + ; inner_ul <- TcM.readTcRef inner_ul_ref
|
|
| 1923 | + ; TcM.traceTc "report_coarse" $
|
|
| 1924 | + text "inner_lvl =" <+> ppr inner_ul
|
|
| 1925 | + ; return (inner_ul, res) }
|
|
| 1925 | 1926 | |
| 1926 | 1927 | report_fine_grain_unifs :: TcSEnv -> (TcSEnv -> TcM a)
|
| 1927 | 1928 | -> TcM (TcTyVarSet, a)
|
| ... | ... | @@ -118,28 +118,34 @@ simplify_loop n limit definitely_redo_implications |
| 118 | 118 | , int (lengthBag simples) <+> text "simples to solve" ])
|
| 119 | 119 | ; traceTcS "simplify_loop: wc =" (ppr wc)
|
| 120 | 120 | |
| 121 | - ; (simple_unif_happened, wc1)
|
|
| 121 | + ; ambient_lvl <- getTcLevel
|
|
| 122 | + ; (simple_unif_lvl, wc1)
|
|
| 122 | 123 | <- reportCoarseGrainUnifications $ -- See Note [Superclass iteration]
|
| 123 | 124 | solveSimpleWanteds simples
|
| 124 | 125 | -- Any insoluble constraints are in 'simples' and so get rewritten
|
| 125 | 126 | -- See Note [Rewrite insolubles] in GHC.Tc.Solver.InertSet
|
| 126 | 127 | |
| 127 | 128 | -- Next, solve implications from wc_impl
|
| 128 | - ; (impl_unif_happened, implics')
|
|
| 129 | + ; let simple_unif_happened = ambient_lvl `deeperThanOrSame` simple_unif_lvl
|
|
| 130 | + ; (implic_unif_lvl, implics')
|
|
| 129 | 131 | <- if not (definitely_redo_implications -- See Note [Superclass iteration]
|
| 130 | 132 | || simple_unif_happened) -- for this conditional
|
| 131 | - then return (False, implics)
|
|
| 133 | + then return (infiniteTcLevel, implics)
|
|
| 132 | 134 | else reportCoarseGrainUnifications $
|
| 133 | 135 | solveNestedImplications implics
|
| 134 | 136 | |
| 135 | 137 | ; let wc' = wc1 { wc_impl = wc_impl wc1 `unionBags` implics' }
|
| 136 | 138 | |
| 137 | - ; csTraceTcS $ text "unif_happened" <+> ppr impl_unif_happened
|
|
| 138 | - |
|
| 139 | 139 | -- We iterate the loop only if the /implications/ did some relevant
|
| 140 | - -- unification. Even if the /simples/ did unifications we don't need
|
|
| 141 | - -- to re-do them.
|
|
| 142 | - ; maybe_simplify_again (n+1) limit impl_unif_happened wc' }
|
|
| 140 | + -- unification, hence looking only at `implic_unif_lvl`. (Even if the
|
|
| 141 | + -- /simples/ did unifications we don't need to re-do them.)
|
|
| 142 | + -- Also note that we only iterate if `implic_unify_lvl` is /equal to/
|
|
| 143 | + -- the current level; if it is less , we'll iterate some outer level,
|
|
| 144 | + -- which will bring us back here anyway.
|
|
| 145 | + -- See Note [When to iterate the solver: unifications]
|
|
| 146 | + ; let implic_unif_happened = implic_unif_lvl `sameDepthAs` ambient_lvl
|
|
| 147 | + ; csTraceTcS $ text "implic_unif_happened" <+> ppr implic_unif_happened
|
|
| 148 | + ; maybe_simplify_again (n+1) limit implic_unif_happened wc' }
|
|
| 143 | 149 | |
| 144 | 150 | data NextAction
|
| 145 | 151 | = NA_Stop -- Just return the WantedConstraints
|
| ... | ... | @@ -148,7 +154,9 @@ data NextAction |
| 148 | 154 | Bool -- See `definitely_redo_implications` in the comment
|
| 149 | 155 | -- for `simplify_loop`
|
| 150 | 156 | |
| 151 | -maybe_simplify_again :: Int -> IntWithInf -> Bool
|
|
| 157 | +maybe_simplify_again :: Int -> IntWithInf
|
|
| 158 | + -> Bool -- True <=> Solving the implications did some unifications
|
|
| 159 | + -- at the current level; so iterate
|
|
| 152 | 160 | -> WantedConstraints -> TcS WantedConstraints
|
| 153 | 161 | maybe_simplify_again n limit unif_happened wc@(WC { wc_simple = simples })
|
| 154 | 162 | = do { -- Look for reasons to stop or continue
|
| ... | ... | @@ -222,10 +230,10 @@ and if so it seems a pity to waste time iterating the implications (forall b. bl |
| 222 | 230 | (If we add new Given superclasses it's a different matter: it's really worth looking
|
| 223 | 231 | at the implications.)
|
| 224 | 232 | |
| 225 | -Hence the definitely_redo_implications flag to simplify_loop. It's usually
|
|
| 226 | -True, but False in the case where the only reason to iterate is new Wanted
|
|
| 227 | -superclasses. In that case we check whether the new Wanteds actually led to
|
|
| 228 | -any new unifications, and iterate the implications only if so.
|
|
| 233 | +Hence the `definitely_redo_implications` flag to `simplify_loop`. It's usually True,
|
|
| 234 | +but False in the case where the only reason to iterate is new Wanted superclasses.
|
|
| 235 | +In that case we check whether the new Wanteds actually led to any new unifications
|
|
| 236 | +(at all), and iterate the implications only if so.
|
|
| 229 | 237 | |
| 230 | 238 | Note [When to iterate the solver: unifications]
|
| 231 | 239 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -45,7 +45,7 @@ module GHC.Tc.Utils.TcType ( |
| 45 | 45 | TcLevel(..), topTcLevel, pushTcLevel, isTopTcLevel,
|
| 46 | 46 | strictlyDeeperThan, deeperThanOrSame, sameDepthAs,
|
| 47 | 47 | tcTypeLevel, tcTyVarLevel, maxTcLevel, minTcLevel,
|
| 48 | - infiniteTcLevel,
|
|
| 48 | + infiniteTcLevel, isInfiniteTcLevel,
|
|
| 49 | 49 | |
| 50 | 50 | --------------------------------
|
| 51 | 51 | -- MetaDetails
|
| ... | ... | @@ -879,6 +879,10 @@ isTopTcLevel :: TcLevel -> Bool |
| 879 | 879 | isTopTcLevel (TcLevel 0) = True
|
| 880 | 880 | isTopTcLevel _ = False
|
| 881 | 881 | |
| 882 | +isInfiniteTcLevel :: TcLevel -> Bool
|
|
| 883 | +isInfiniteTcLevel QLInstVar = True
|
|
| 884 | +isInfiniteTcLevel _ = False
|
|
| 885 | + |
|
| 882 | 886 | pushTcLevel :: TcLevel -> TcLevel
|
| 883 | 887 | -- See Note [TcLevel assignment]
|
| 884 | 888 | pushTcLevel (TcLevel us) = TcLevel (us + 1)
|
| 1 | +{-# LANGUAGE GADTs #-}
|
|
| 2 | + |
|
| 3 | +module T26582 where
|
|
| 4 | + |
|
| 5 | +sametype :: a -> a -> Int
|
|
| 6 | +sametype = sametype
|
|
| 7 | + |
|
| 8 | +f :: Eq a => (a->Int) -> Int
|
|
| 9 | +f = f
|
|
| 10 | + |
|
| 11 | +data T b where T1 :: T Bool
|
|
| 12 | + |
|
| 13 | +g1 :: T b -> Int
|
|
| 14 | +g1 v = f (\x -> case v of { T1 -> sametype x True })
|
|
| 15 | + |
|
| 16 | +g2 :: Eq c => c -> T b -> Int
|
|
| 17 | +g2 c v = f (\x -> case v of { T1 -> sametype x c })
|
|
| 18 | + |
|
| 19 | +{- The point is that we get something like
|
|
| 20 | + |
|
| 21 | + Wanted: [W] d : Eq alpha[1]
|
|
| 22 | + Implication
|
|
| 23 | + level: 2
|
|
| 24 | + Given: b~Bool
|
|
| 25 | + |
|
| 26 | + Wanted: [W] alpha[1]~Bool -- For g1
|
|
| 27 | + Wanted: [W] alpha[1]~c -- For g2
|
|
| 28 | + |
|
| 29 | +So alpha is untouchable under the (b~Bool) from the GADT.
|
|
| 30 | +And yet in the end it's easy to solve
|
|
| 31 | +via alpha:=Bool, or alpha:=c resp
|
|
| 32 | + |
|
| 33 | +But having done that defaulting we must then remember to
|
|
| 34 | +solved that `d : Eq alpha`! We forgot to so so in #26582.
|
|
| 35 | +-} |
| ... | ... | @@ -956,3 +956,4 @@ test('T26457', normal, compile, ['']) |
| 956 | 956 | test('T17705', normal, compile, [''])
|
| 957 | 957 | test('T14745', normal, compile, [''])
|
| 958 | 958 | test('T26451', normal, compile, [''])
|
| 959 | +test('T26582', normal, compile, ['']) |