Simon Peyton Jones pushed to branch wip/T23162-spj at Glasgow Haskell Compiler / GHC Commits: e61cec2a by Simon Peyton Jones at 2025-09-26T10:32:06+01:00 Accept error message changes Plus compile time improvement Metrics: compile_time/bytes allocated Baseline Test value New value Change ---------------------- -------------------------------------- T5030(normal) 173,839,232 148,115,248 -14.8% GOOD hard_hole_fits(normal) 286,768,048 284,015,416 -1.0% geo. mean -0.2% minimum -14.8% maximum +0.3% Metric Decrease: T5030 - - - - - 17 changed files: - compiler/GHC/Tc/Errors.hs - compiler/GHC/Tc/Gen/App.hs - compiler/GHC/Tc/Solver/FunDeps.hs - compiler/GHC/Tc/Types/Constraint.hs - compiler/GHC/Tc/Types/Origin.hs - compiler/GHC/Tc/Utils/TcMType.hs - testsuite/tests/default/default-fail05.stderr - testsuite/tests/indexed-types/should_fail/T1897b.stderr - testsuite/tests/indexed-types/should_fail/T9662.stderr - testsuite/tests/parser/should_fail/RecordDotSyntaxFail10.stderr - testsuite/tests/parser/should_fail/RecordDotSyntaxFail13.stderr - testsuite/tests/partial-sigs/should_fail/T14040a.stderr - testsuite/tests/rep-poly/RepPolyRightSection.stderr - testsuite/tests/typecheck/no_skolem_info/T14040.stderr - − testsuite/tests/typecheck/should_compile/T13651.stderr - testsuite/tests/typecheck/should_compile/all.T - testsuite/tests/typecheck/should_fail/T8603.stderr Changes: ===================================== compiler/GHC/Tc/Errors.hs ===================================== @@ -778,8 +778,8 @@ Which errors are suppressed? Historical (SCE2). Fundep constraints never "escape" into the main solver and so never show up in error messages. - See Note [Functional dependencies in type inference] inb GHC.Tc.Solver.FunDeps. - So this wrinkle is now just a historical note. + See (SOLVE-FD) in Note [Overview of functional dependencies in type inference] + in GHC.Tc.Solver.FunDeps. So this wrinkle is now just a historical note. Errors which arise from the interaction of two Wanted fun-dep constraints. Example: ===================================== compiler/GHC/Tc/Gen/App.hs ===================================== @@ -929,7 +929,7 @@ newFlexiTyVarQL :: QLFlag -> OccName -> MetaInfo -> TcKind -> TcM TcTyVar newFlexiTyVarQL do_ql occ info kind = do { lvl <- getTcLevelQL do_ql ; ref <- newMutVar Flexi - ; name <- newSysName occ -- See Note [Name of an unification variable] + ; name <- newSysName occ -- See Note [Name of a unification variable] -- in GHC.Tc.Utils.TcMType ; let details = MetaTv { mtv_info = info , mtv_ref = ref ===================================== compiler/GHC/Tc/Solver/FunDeps.hs ===================================== @@ -41,33 +41,33 @@ import GHC.Data.Pair import Data.Maybe( mapMaybe ) -{- Note [Functional dependencies in type inference] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +{- Note [Overview of functional dependencies in type inference] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Here is our plan for dealing with functional dependencies * When we have failed to solve a Wanted constraint, do this - 1. Generate any fundep-equalities [FunDepEqns] from that constraint. - 2. Try to solve that [FunDepEqns] - 3. If any unifications happened, send the constraint back to the - start of the pipeline - -* Step (1) How we generate those [FunDepEqns] varies: + - (GEN-FD) Generate any fundep-equalities [FunDepEqns] from that constraint. + - (SOLVE-FD) Try to solve that [FunDepEqns] + - (KICK-FD) If any unifications happened, + * kick out any inert constraints that mention the unified variables + * send the current constraint back to the start of the pipeline; + might now be soluble, and it probably isn't inert + +* (GEN-FD) How we generate those [FunDepEqns] varies: - tryDictFunDeps: for class constraints (C t1 .. tn) we look at top-level instances and inert Givens - tryEqFunDeps: for type-family equalities (F t1 .. tn ~ ty) we look at top-level family instances and inert Given family equalities -* Step (2). We use `solveFunDeps` to solve the [FunDepEqns] in a nested +* (SOLVE-FD) We use `solveFunDeps` to solve the [FunDepEqns] in a nested solver. Key property: The ONLY effect of `solveFunDeps` is possibly to perform unifications: - - It entirely discards any unsolved fundep equalities. - - It entirely discards any evidence arising from solving fundep equalities -* Step (3) if we did any unifications in Step (2), we start again with the +* (KICK-FD) if we did any unifications in (SOLVE-FD), we start again with the current unsolved Wanted. It might now be soluble! * For Given constraints, things are different: @@ -518,7 +518,8 @@ mkTopUserFamEqFDs fam_tc inj_flags work_args work_rhs in_scope = mkInScopeSet (tyCoVarsOfType work_rhs) trim_qtvs :: Subst -> [TcTyVar] -> (Subst,[TcTyVar]) - -- Tricky stuff: see (TF1) in Note [Fundeps and top-level family instances] + -- Tricky stuff: see (TIF1) in + -- Note [Type inference for type families with injectivity] trim_qtvs subst [] = (subst, []) trim_qtvs subst (tv:tvs) | tv `elemSubst` subst = trim_qtvs subst tvs @@ -765,7 +766,7 @@ solveFunDeps :: CtEvidence -- The work item -- -- The returned Bool is True if some unifications happened -- --- See Note [Overview of fundeps] +-- See (SOLVE-FD) in Note [Overview of functional dependencies in type inference] solveFunDeps work_ev fd_eqns | null fd_eqns = return False -- Common case no-op ===================================== compiler/GHC/Tc/Types/Constraint.hs ===================================== @@ -1330,7 +1330,7 @@ can't be solved. But not quite all such constraints; see wrinkles. (IW4) Historical note: we used to have equalities arising from Wanted/Wanted fundep interactions, which we did not want to treat as insoluble. But now such fundep constraints never escape. - See Note [Functional dependencies in type inference] + See Note [Overview of functional dependencies in type inference] Note [Insoluble holes] ~~~~~~~~~~~~~~~~~~~~~~ ===================================== compiler/GHC/Tc/Types/Origin.hs ===================================== @@ -598,9 +598,10 @@ data CtOrigin | ArrowCmdOrigin -- Arising from an arrow command | AnnOrigin -- An annotation - | FunDepOrigin -- A functional dependency. We don't need auxiliary info - -- because fundep constraints never show up in errors - -- See Note [Functional dependencies in type inference] + | FunDepOrigin -- A functional dependency. + -- We don't need auxiliary info because fundep constraints + -- never show up in errors. See (SOLVE-FD) in + -- Note [Overview of functional dependencies in type inference] | InjTFOrigin1 -- injective type family equation combining PredType CtOrigin RealSrcSpan -- This constraint arising from ... ===================================== compiler/GHC/Tc/Utils/TcMType.hs ===================================== @@ -716,14 +716,14 @@ Proposal 29). Note [Name of a unification variable] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -We give unification variables a /System/ Name, which is eagerly elmininated -the the unifier; see GHC.Tc.Utils.Unify.nicer_to_update_tv1, and -GHC.Tc.Solver.Equality.canEqTyVarTyVar (nicer_to_update_tv2) - -Note [Name of an instantiated type variable] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -At the moment we give a unification variable a System Name, which -influences the way it is tidied; see TypeRep.tidyTyVarBndr. +We give unification variables a /System/ Name, which is treated specially +in two ways + +* It is eagerly elmininated the the unifier; see + GHC.Tc.Utils.Unify.nicer_to_update_tv1, and + GHC.Tc.Solver.Equality.canEqTyVarTyVar (nicer_to_update_tv2) + +* It influences the way it is tidied; see TypeRep.tidyTyVarBndr. -} newMetaTyVarName :: FastString -> TcM Name @@ -732,7 +732,7 @@ newMetaTyVarName str = newSysName (mkTyVarOccFS str) cloneMetaTyVarName :: Name -> TcM Name --- See Note [Name of an instantiated type variable] +-- Makes a /System/ Name; see Note [Name of a unification variable] cloneMetaTyVarName name = newSysName (nameOccName name) ===================================== testsuite/tests/default/default-fail05.stderr ===================================== @@ -1,7 +1,7 @@ default-fail05.hs:11:10: error: [GHC-39999] - • Ambiguous type variable ‘t0’ arising from a use of ‘toList’ - prevents the constraint ‘(Foldable t0)’ from being solved. - Probable fix: use a type annotation to specify what ‘t0’ should be. + • Ambiguous type variable ‘f0’ arising from a use of ‘toList’ + prevents the constraint ‘(Foldable f0)’ from being solved. + Probable fix: use a type annotation to specify what ‘f0’ should be. Potentially matching instances: instance Foldable (Either a) -- Defined in ‘GHC.Internal.Data.Foldable’ @@ -14,9 +14,9 @@ default-fail05.hs:11:10: error: [GHC-39999] In a stmt of a 'do' block: print (toList $ pure 21) default-fail05.hs:11:19: error: [GHC-39999] - • Ambiguous type variable ‘t0’ arising from a use of ‘pure’ - prevents the constraint ‘(Applicative t0)’ from being solved. - Probable fix: use a type annotation to specify what ‘t0’ should be. + • Ambiguous type variable ‘f0’ arising from a use of ‘pure’ + prevents the constraint ‘(Applicative f0)’ from being solved. + Probable fix: use a type annotation to specify what ‘f0’ should be. Potentially matching instances: instance Applicative IO -- Defined in ‘GHC.Internal.Base’ instance Applicative Maybe -- Defined in ‘GHC.Internal.Base’ @@ -28,11 +28,11 @@ default-fail05.hs:11:19: error: [GHC-39999] In a stmt of a 'do' block: print (toList $ pure 21) default-fail05.hs:12:3: error: [GHC-39999] - • Ambiguous type variable ‘t1’ arising from a use of ‘traverse’ - prevents the constraint ‘(Traversable t1)’ from being solved. + • Ambiguous type variable ‘t0’ arising from a use of ‘traverse’ + prevents the constraint ‘(Traversable t0)’ from being solved. Relevant bindings include - main :: IO (t1 ()) (bound at default-fail05.hs:10:1) - Probable fix: use a type annotation to specify what ‘t1’ should be. + main :: IO (t0 ()) (bound at default-fail05.hs:10:1) + Probable fix: use a type annotation to specify what ‘t0’ should be. Potentially matching instances: instance Traversable (Either a) -- Defined in ‘GHC.Internal.Data.Traversable’ @@ -51,11 +51,11 @@ default-fail05.hs:12:3: error: [GHC-39999] traverse print (pure 42) default-fail05.hs:12:19: error: [GHC-39999] - • Ambiguous type variable ‘t1’ arising from a use of ‘pure’ - prevents the constraint ‘(Applicative t1)’ from being solved. + • Ambiguous type variable ‘t0’ arising from a use of ‘pure’ + prevents the constraint ‘(Applicative t0)’ from being solved. Relevant bindings include - main :: IO (t1 ()) (bound at default-fail05.hs:10:1) - Probable fix: use a type annotation to specify what ‘t1’ should be. + main :: IO (t0 ()) (bound at default-fail05.hs:10:1) + Probable fix: use a type annotation to specify what ‘t0’ should be. Potentially matching instances: instance Applicative IO -- Defined in ‘GHC.Internal.Base’ instance Applicative Maybe -- Defined in ‘GHC.Internal.Base’ ===================================== testsuite/tests/indexed-types/should_fail/T1897b.stderr ===================================== @@ -1,14 +1,14 @@ T1897b.hs:16:1: error: [GHC-83865] - • Couldn't match type: Depend a0 - with: Depend a - Expected: t (Depend a) -> Bool - Actual: t (Depend a0) -> Bool + • Couldn't match type: Depend b0 + with: Depend b + Expected: t (Depend b) -> Bool + Actual: t (Depend b0) -> Bool Note: ‘Depend’ is a non-injective type family. - The type variable ‘a0’ is ambiguous + The type variable ‘b0’ is ambiguous • In the ambiguity check for the inferred type for ‘isValid’ To defer the ambiguity check to use sites, enable AllowAmbiguousTypes When checking the inferred type - isValid :: forall {t :: * -> *} {a}. - (Foldable t, Bug a) => - t (Depend a) -> Bool + isValid :: forall {t :: * -> *} {b}. + (Foldable t, Bug b) => + t (Depend b) -> Bool ===================================== testsuite/tests/indexed-types/should_fail/T9662.stderr ===================================== @@ -1,12 +1,12 @@ T9662.hs:49:8: error: [GHC-25897] - • Couldn't match type ‘k’ with ‘Int’ + • Couldn't match type ‘n’ with ‘Int’ Expected: Exp (((sh :. k) :. m) :. n) -> Exp (((sh :. m) :. n) :. k) Actual: Exp (Tuple (((Atom a0 :. Atom Int) :. Atom Int) :. Atom Int)) -> Exp (Plain (((Unlifted (Atom a0) :. Exp Int) :. Exp Int) :. Exp Int)) - ‘k’ is a rigid type variable bound by + ‘n’ is a rigid type variable bound by the type signature for: test :: forall sh k m n. Shape (((sh :. k) :. m) :. n) -> Shape (((sh :. m) :. n) :. k) ===================================== testsuite/tests/parser/should_fail/RecordDotSyntaxFail10.stderr ===================================== @@ -1,10 +1,9 @@ -RecordDotSyntaxFail10.hs:40:11: error: [GHC-18872] - • Couldn't match type ‘Int’ with ‘[Char]’ +RecordDotSyntaxFail10.hs:40:11: error: [GHC-39999] + • No instance for ‘HasField "quux" Quux String’ • In the second argument of ‘($)’, namely ‘a {foo.bar.baz.quux}’ In a stmt of a 'do' block: print $ a {foo.bar.baz.quux} In the expression: do let a = Foo {foo = ...} - do let a = ... let quux = "Expecto patronum!" print $ a {foo.bar.baz.quux} ===================================== testsuite/tests/parser/should_fail/RecordDotSyntaxFail13.stderr ===================================== @@ -1,13 +1,10 @@ -RecordDotSyntaxFail13.hs:26:11: error: [GHC-18872] - • Couldn't match type ‘Int’ with ‘Foo -> Int’ - arising from a functional dependency between: - constraint ‘HasField "foo" Foo (Foo -> Int)’ - arising from a record update - instance ‘HasField "foo" Foo Int’ - at RecordDotSyntaxFail13.hs:21:10-31 +RecordDotSyntaxFail13.hs:26:11: error: [GHC-39999] + • No instance for ‘HasField "foo" Foo (Foo -> Int)’ + arising from a record update + (maybe you haven't applied a function to enough arguments?) • In the second argument of ‘($)’, namely ‘a {foo}’ In a stmt of a 'do' block: print $ a {foo} In the expression: - do let a = ... + do let a = Foo {foo = 12} print $ a {foo} ===================================== testsuite/tests/partial-sigs/should_fail/T14040a.stderr ===================================== @@ -1,6 +1,6 @@ T14040a.hs:26:46: error: [GHC-46956] - • Couldn't match kind ‘k1’ with ‘WeirdList z’ - Expected kind ‘WeirdList k1’, + • Couldn't match kind ‘k0’ with ‘WeirdList z’ + Expected kind ‘WeirdList k0’, but ‘xs’ has kind ‘WeirdList (WeirdList z)’ because kind variable ‘z’ would escape its scope This (rigid, skolem) kind variable is bound by @@ -24,8 +24,8 @@ T14040a.hs:26:46: error: [GHC-46956] -> p _ wl T14040a.hs:27:27: error: [GHC-46956] - • Couldn't match kind ‘k0’ with ‘z’ - Expected kind ‘WeirdList k0’, + • Couldn't match kind ‘k1’ with ‘z’ + Expected kind ‘WeirdList k1’, but ‘WeirdCons x xs’ has kind ‘WeirdList z’ because kind variable ‘z’ would escape its scope This (rigid, skolem) kind variable is bound by ===================================== testsuite/tests/rep-poly/RepPolyRightSection.stderr ===================================== @@ -8,6 +8,7 @@ RepPolyRightSection.hs:14:11: error: [GHC-55287] • * Cannot unify ‘r’ with the type variable ‘q0’ because the former is not a concrete ‘RuntimeRep’. - • In the expression: `g` undefined + • In the expression: g + In the expression: `g` undefined In an equation for ‘test2’: test2 = (`g` undefined) ===================================== testsuite/tests/typecheck/no_skolem_info/T14040.stderr ===================================== @@ -1,6 +1,6 @@ T14040.hs:27:46: error: [GHC-46956] - • Couldn't match kind ‘k1’ with ‘WeirdList z’ - Expected kind ‘WeirdList k1’, + • Couldn't match kind ‘k0’ with ‘WeirdList z’ + Expected kind ‘WeirdList k0’, but ‘xs’ has kind ‘WeirdList (WeirdList z)’ because kind variable ‘z’ would escape its scope This (rigid, skolem) kind variable is bound by @@ -24,8 +24,8 @@ T14040.hs:27:46: error: [GHC-46956] -> p _ wl T14040.hs:28:27: error: [GHC-46956] - • Couldn't match kind ‘k0’ with ‘z’ - Expected kind ‘WeirdList k0’, + • Couldn't match kind ‘k1’ with ‘z’ + Expected kind ‘WeirdList k1’, but ‘WeirdCons x xs’ has kind ‘WeirdList z’ because kind variable ‘z’ would escape its scope This (rigid, skolem) kind variable is bound by ===================================== testsuite/tests/typecheck/should_compile/T13651.stderr deleted ===================================== @@ -1,22 +0,0 @@ - -T13651.hs:12:8: error: [GHC-25897] - • Could not deduce ‘cr ~ Bar h (Foo r)’ - from the context: (F cr cu ~ Bar h (Bar r u), - F cu cs ~ Bar (Foo h) (Bar u s)) - bound by the type signature for: - foo :: forall cr cu h r u cs s. - (F cr cu ~ Bar h (Bar r u), F cu cs ~ Bar (Foo h) (Bar u s)) => - Bar h (Bar r u) -> Bar (Foo h) (Bar u s) -> Foo (cr -> cs) - at T13651.hs:(12,8)-(14,65) - ‘cr’ is a rigid type variable bound by - the type signature for: - foo :: forall cr cu h r u cs s. - (F cr cu ~ Bar h (Bar r u), F cu cs ~ Bar (Foo h) (Bar u s)) => - Bar h (Bar r u) -> Bar (Foo h) (Bar u s) -> Foo (cr -> cs) - at T13651.hs:(12,8)-(14,65) - • In the ambiguity check for ‘foo’ - To defer the ambiguity check to use sites, enable AllowAmbiguousTypes - In the type signature: - foo :: (F cr cu ~ Bar h (Bar r u), - F cu cs ~ Bar (Foo h) (Bar u s)) => - Bar h (Bar r u) -> Bar (Foo h) (Bar u s) -> Foo (cr -> cs) ===================================== testsuite/tests/typecheck/should_compile/all.T ===================================== @@ -586,7 +586,7 @@ test('T13594', normal, compile_fail, ['']) test('T13603', normal, compile, ['']) test('T13333', normal, compile, ['']) test('T13585', [extra_files(['T13585.hs', 'T13585a.hs', 'T13585b.hs'])], makefile_test, []) -test('T13651', normal, compile_fail, ['']) +test('T13651', normal, compile, ['']) test('T13651a', normal, compile, ['']) test('T13680', normal, compile, ['']) test('T13785', normal, compile, ['']) ===================================== testsuite/tests/typecheck/should_fail/T8603.stderr ===================================== @@ -3,8 +3,8 @@ T8603.hs:33:17: error: [GHC-18872] When matching types m0 :: * -> * [a2] :: * - Expected: [a2] -> StateT s RV a0 - Actual: t0 m0 (StateT s RV a0) + Expected: [a2] -> StateT s RV a1 + Actual: t0 m0 (StateT s RV a1) • The function ‘lift’ is applied to two visible arguments, but its type ‘(Control.Monad.Trans.Class.MonadTrans t, Monad m) => m a -> t m a’ View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e61cec2ab4aed4b049d29121d8f7dbd4... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e61cec2ab4aed4b049d29121d8f7dbd4... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Simon Peyton Jones (@simonpj)