Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
-
45428f88
by sheaf at 2026-03-26T03:51:31-04:00
5 changed files:
- compiler/GHC/Tc/Utils/Unify.hs
- testsuite/tests/typecheck/should_compile/T26225.hs
- + testsuite/tests/typecheck/should_fail/T26823.hs
- + testsuite/tests/typecheck/should_fail/T26823.stderr
- testsuite/tests/typecheck/should_fail/all.T
Changes:
| ... | ... | @@ -1948,6 +1948,41 @@ the LHS vs the new RHS. And vice-versa (if it's the RHS that is a FunTy). |
| 1948 | 1948 | |
| 1949 | 1949 | See T11305 and T26225 for examples of when this is important.
|
| 1950 | 1950 | |
| 1951 | +Wrinkle [Avoiding a loop in tc_sub_type_deep]
|
|
| 1952 | + |
|
| 1953 | + In #26823, we had:
|
|
| 1954 | + |
|
| 1955 | + alpha <= a -> alpha
|
|
| 1956 | + |
|
| 1957 | + If we simply unified the two types, the occurs-check would trigger.
|
|
| 1958 | + In deep subsumption however, we need to be careful, as we might do the
|
|
| 1959 | + following:
|
|
| 1960 | + |
|
| 1961 | + A1. Create fresh metavariables beta, gamma
|
|
| 1962 | + A2. Unify alpha ~ beta -> gamma
|
|
| 1963 | + A3. Decompose "beta -> gamma <= a -> (beta -> gamma)", obtaining
|
|
| 1964 | + a <= beta and gamma <= beta -> gamma
|
|
| 1965 | + A4. Recur with gamma <= beta -> gamma
|
|
| 1966 | + |
|
| 1967 | + If we do this, we enter an infinite loop and GHC hangs at compile time.
|
|
| 1968 | + To avoid this, we must first recur, before unifying. So the above becomes:
|
|
| 1969 | + |
|
| 1970 | + B1 (like A1). Create fresh metavariables beta, gamma
|
|
| 1971 | + B2 (like A3). Decompose "beta -> gamma <= a -> alpha", obtaining
|
|
| 1972 | + a <= beta and gamma <= alpha
|
|
| 1973 | + B3. Solve these two sub-problems by unification
|
|
| 1974 | + a ~ beta, gamma ~ alpha
|
|
| 1975 | + B4 (like A2). Then, and only then, unify alpha ~ beta->gamma
|
|
| 1976 | + |
|
| 1977 | + With this approach, GHC will be left with the following unifications:
|
|
| 1978 | + |
|
| 1979 | + - alpha ~ (beta -> gamma)
|
|
| 1980 | + - a ~ beta
|
|
| 1981 | + - gamma ~ alpha
|
|
| 1982 | + |
|
| 1983 | + GHC will fail to solve this unification problem due to an occurs check
|
|
| 1984 | + failure, thus rejecting the program with a type error (as desired).
|
|
| 1985 | + |
|
| 1951 | 1986 | Note [Deep subsumption and required foralls]
|
| 1952 | 1987 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 1953 | 1988 | A required forall, (forall a -> ty) behaves like a "rho-type", one with no
|
| ... | ... | @@ -2117,8 +2152,9 @@ tc_sub_type_deep fun_pos@(tc_fun, pos) ds_depth unify inst_orig ctxt ty_actual t |
| 2117 | 2152 | ; exp_arg <- newOpenFlexiTyVarTy -- NB: no FRR check needed; we might not need to eta-expand
|
| 2118 | 2153 | ; exp_res <- newOpenFlexiTyVarTy
|
| 2119 | 2154 | ; let exp_funTy = FunTy { ft_af = af1, ft_mult = exp_mult, ft_arg = exp_arg, ft_res = exp_res }
|
| 2120 | - ; unify_wrap <- just_unify exp_funTy ty_e
|
|
| 2155 | + -- Recur before unifying; see Wrinkle [Avoiding a loop in tc_sub_type_deep]
|
|
| 2121 | 2156 | ; fun_wrap <- go_fun af1 act_mult act_arg act_res af1 exp_mult exp_arg exp_res
|
| 2157 | + ; unify_wrap <- just_unify exp_funTy ty_e
|
|
| 2122 | 2158 | ; return $ unify_wrap <.> fun_wrap
|
| 2123 | 2159 | -- unify_wrap :: exp_funTy ~~> ty_e
|
| 2124 | 2160 | -- fun_wrap :: ty_a ~~> exp_funTy
|
| ... | ... | @@ -2129,8 +2165,9 @@ tc_sub_type_deep fun_pos@(tc_fun, pos) ds_depth unify inst_orig ctxt ty_actual t |
| 2129 | 2165 | ; act_arg <- newOpenFlexiTyVarTy -- NB: no FRR check needed; we might not need to eta-expand
|
| 2130 | 2166 | ; act_res <- newOpenFlexiTyVarTy
|
| 2131 | 2167 | ; let act_funTy = FunTy { ft_af = af2, ft_mult = act_mult, ft_arg = act_arg, ft_res = act_res }
|
| 2132 | - ; unify_wrap <- just_unify ty_a act_funTy
|
|
| 2168 | + -- Recur before unifying; see Wrinkle [Avoiding a loop in tc_sub_type_deep]
|
|
| 2133 | 2169 | ; fun_wrap <- go_fun af2 act_mult act_arg act_res af2 exp_mult exp_arg exp_res
|
| 2170 | + ; unify_wrap <- just_unify ty_a act_funTy
|
|
| 2134 | 2171 | ; return $ fun_wrap <.> unify_wrap
|
| 2135 | 2172 | -- unify_wrap :: ty_a ~~> act_funTy
|
| 2136 | 2173 | -- fun_wrap :: act_funTy ~~> ty_e
|
| ... | ... | @@ -26,7 +26,7 @@ ex0 = |
| 26 | 26 | in g f
|
| 27 | 27 | |
| 28 | 28 | -- ((∀ a. a->a) -> Int) -> Bool ⊑ α[tau]
|
| 29 | --- Rejected by GHC up to and including 9.14.
|
|
| 29 | +-- Rejected by GHC up to and including 9.12.
|
|
| 30 | 30 | ex1' :: ()
|
| 31 | 31 | ex1' =
|
| 32 | 32 | let
|
| ... | ... | @@ -38,7 +38,7 @@ ex1' = |
| 38 | 38 | -- Couldn't match expected type ‘α’ with actual type ‘((∀ a. a -> a) -> Int) -> Bool’
|
| 39 | 39 | |
| 40 | 40 | -- ((∀ a. a->a) -> Int) -> Bool ⊑ β[tau] Bool
|
| 41 | --- Rejected by GHC up to and including 9.14.
|
|
| 41 | +-- Rejected by GHC up to and including 9.12.
|
|
| 42 | 42 | ex2' :: ()
|
| 43 | 43 | ex2' =
|
| 44 | 44 | let
|
| ... | ... | @@ -50,7 +50,7 @@ ex2' = |
| 50 | 50 | -- Couldn't match expected type ‘β’ with actual type ‘(->) ((∀ a. a -> a) -> Int)’
|
| 51 | 51 | |
| 52 | 52 | -- ex3 :: β[tau] Bool ⊑ (∀ a. a->a) -> Bool
|
| 53 | --- Rejected by GHC up to and including 9.14.
|
|
| 53 | +-- Rejected by GHC up to and including 9.12.
|
|
| 54 | 54 | ex3 :: ()
|
| 55 | 55 | ex3 =
|
| 56 | 56 | let
|
| ... | ... | @@ -62,7 +62,7 @@ ex3 = |
| 62 | 62 | -- Couldn't match expected type ‘β’ with actual type ‘(->) (∀ a. a -> a)’
|
| 63 | 63 | |
| 64 | 64 | -- ex3' :: F Int Bool ⊑ (∀ a. a->a) -> Bool, where F Int = (->) (Int -> Int)
|
| 65 | --- Rejected by GHC up to and including 9.14.
|
|
| 65 | +-- Rejected by GHC up to and including 9.12.
|
|
| 66 | 66 | ex3' :: ()
|
| 67 | 67 | ex3' =
|
| 68 | 68 | let
|
| 1 | +{-# LANGUAGE DeepSubsumption #-}
|
|
| 2 | + |
|
| 3 | +module T26823 where
|
|
| 4 | + |
|
| 5 | +allocArray :: Int -> IO ()
|
|
| 6 | +allocArray n = do
|
|
| 7 | + let
|
|
| 8 | + !off = 18
|
|
| 9 | + !size = 8
|
|
| 10 | + !vecAli = size
|
|
| 11 | + |
|
| 12 | + !rem = off `rem` vecAli
|
|
| 13 | + !start = if rem == 0 then off else off + ( vecAli - rem )
|
|
| 14 | + |
|
| 15 | + return () |
| 1 | +T26823.hs:12:14: error: [GHC-25897]
|
|
| 2 | + • Couldn't match expected type ‘a0 -> a0 -> t’ with actual type ‘t’
|
|
| 3 | + ‘t’ is a rigid type variable bound by
|
|
| 4 | + the inferred type of rem :: a0 -> a0 -> t
|
|
| 5 | + at T26823.hs:12:5-29
|
|
| 6 | + • In the expression: off `rem` vecAli
|
|
| 7 | + In an equation for ‘rem’: !rem = off `rem` vecAli
|
|
| 8 | + In a stmt of a 'do' block:
|
|
| 9 | + let !off = 18
|
|
| 10 | + !size = 8
|
|
| 11 | + !vecAli = size
|
|
| 12 | + !rem = off `rem` vecAli
|
|
| 13 | + !start = if rem == 0 then off else off + (vecAli - rem)
|
|
| 14 | + • Relevant bindings include
|
|
| 15 | + rem :: a0 -> a0 -> t (bound at T26823.hs:12:6)
|
|
| 16 | + off :: a0 (bound at T26823.hs:8:6)
|
|
| 17 | + vecAli :: a0 (bound at T26823.hs:10:6)
|
|
| 18 | + size :: a0 (bound at T26823.hs:9:6)
|
|
| 19 | + |
|
| 20 | +T26823.hs:13:57: error: [GHC-27958]
|
|
| 21 | + • Couldn't match expected type ‘a0’
|
|
| 22 | + with actual type ‘a0 -> a0 -> t0’
|
|
| 23 | + • In the second argument of ‘(-)’, namely ‘rem’
|
|
| 24 | + In the second argument of ‘(+)’, namely ‘(vecAli - rem)’
|
|
| 25 | + In the expression: off + (vecAli - rem)
|
|
| 26 | + • Relevant bindings include
|
|
| 27 | + start :: a0 (bound at T26823.hs:13:6)
|
|
| 28 | + rem :: forall {t}. a0 -> a0 -> t (bound at T26823.hs:12:6)
|
|
| 29 | + off :: a0 (bound at T26823.hs:8:6)
|
|
| 30 | + vecAli :: a0 (bound at T26823.hs:10:6)
|
|
| 31 | + size :: a0 (bound at T26823.hs:9:6)
|
|
| 32 | + |
| ... | ... | @@ -755,5 +755,6 @@ test('T23162a', normal, compile_fail, ['']) |
| 755 | 755 | test('T23162b', normal, compile_fail, [''])
|
| 756 | 756 | test('T23162c', normal, compile, [''])
|
| 757 | 757 | test('T23162d', normal, compile, [''])
|
| 758 | +test('T26823', normal, compile_fail, [''])
|
|
| 758 | 759 | test('T26861', normal, compile_fail, [''])
|
| 759 | 760 | test('T26862', normal, compile_fail, ['']) |