From 80afdf6be11ae3b5bfd1b09dbc5f5118a9dde55a Mon Sep 17 00:00:00 2001 From: Simon Peyton Jones <simonpj@microsoft.com> Date: Thu, 4 Jul 2019 08:41:12 +0100 Subject: [PATCH] Fix over-eager implication constraint discard Ticket #16247 showed that we were discarding an implication constraint that had empty ic_wanted, when we still needed to keep it so we could check whether it had a bad telescope. Happily it's a one line fix. All the rest is comments! --- compiler/typecheck/TcHsType.hs | 2 ++ compiler/typecheck/TcRnTypes.hs | 44 +++++++++++++++++++++--- compiler/typecheck/TcUnify.hs | 7 ++++ testsuite/tests/polykinds/T16247.hs | 10 ++++++ testsuite/tests/polykinds/T16247.stderr | 7 ++++ testsuite/tests/polykinds/T16247a.hs | 23 +++++++++++++ testsuite/tests/polykinds/T16247a.stderr | 8 +++++ testsuite/tests/polykinds/all.T | 2 ++ 8 files changed, 98 insertions(+), 5 deletions(-) create mode 100644 testsuite/tests/polykinds/T16247.hs create mode 100644 testsuite/tests/polykinds/T16247.stderr create mode 100644 testsuite/tests/polykinds/T16247a.hs create mode 100644 testsuite/tests/polykinds/T16247a.stderr diff --git a/compiler/typecheck/TcHsType.hs b/compiler/typecheck/TcHsType.hs index fac6f2e31cfa..a7e3cf7945fd 100644 --- a/compiler/typecheck/TcHsType.hs +++ b/compiler/typecheck/TcHsType.hs @@ -1652,6 +1652,8 @@ is correct, choosing ImplicationStatus IC_BadTelescope if they aren't. Then, in TcErrors, we report if there is a bad telescope. This way, we can report a suggested ordering to the user if there is a problem. +See also Note [Checking telescopes] in TcRnTypes + Note [Keeping scoped variables in order: Implicit] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When the user implicitly quantifies over variables (say, in a type diff --git a/compiler/typecheck/TcRnTypes.hs b/compiler/typecheck/TcRnTypes.hs index c8d83215fd15..8882bbc6c7dc 100644 --- a/compiler/typecheck/TcRnTypes.hs +++ b/compiler/typecheck/TcRnTypes.hs @@ -2587,11 +2587,9 @@ data Implication ic_skols :: [TcTyVar], -- Introduced skolems ic_info :: SkolemInfo, -- See Note [Skolems in an implication] -- See Note [Shadowing in a constraint] + ic_telescope :: Maybe SDoc, -- User-written telescope, if there is one - -- The list of skolems is order-checked - -- if and only if this is a Just. - -- See Note [Keeping scoped variables in order: Explicit] - -- in TcHsType + -- See Note [Checking telescopes] ic_given :: [EvVar], -- Given evidence variables -- (order does not matter) @@ -2708,7 +2706,43 @@ instance Outputable ImplicStatus where ppr (IC_Solved { ics_dead = dead }) = text "Solved" <+> (braces (text "Dead givens =" <+> ppr dead)) -{- +{- Note [Checking telescopes] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +When kind-checking a /user-written/ type, we might have a "bad telescope" +like this one: + data SameKind :: forall k. k -> k -> Type + type Foo :: forall a k (b :: k). SameKind a b -> Type + +The kind of 'a' mentions 'k' which is bound after 'a'. Oops. + +Knowing this means that unification etc must have happened, so it's +convenient to detect it in the constraint solver: + +* We make a single implication constraint when kind-checking + the 'forall' in Foo's kind, something like + forall a k (b::k). { wanted constraints } + +* Having solved {wanted}, before discarding the now-solved implication, + the costraint solver checks the dependency order of the skolem + variables (ic_skols). This is done in setImplicationStatus. + +* This check is only necessary if the implication was born from a + user-written signature. If, say, it comes from checking a pattern + match that binds existentials, where the type of the data constructor + is known to be valid (it in tcConPat), no need for the check. + + So the check is done if and only if ic_telescope is (Just blah). + +* If ic_telesope is (Just d), the d::SDoc displays the original, + user-written type variables. + +* Be careful /NOT/ to discard an implication with non-Nothing + ic_telescope, even if ic_wanted is empty. We must give the + constraint solver a chance to make that bad-telesope test! Hence + the extra guard in emitResidualTvConstraint; see #16247 + +See also TcHsTYpe Note [Keeping scoped variables in order: Explicit] + Note [Needed evidence variables] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Th ic_need_evs field holds the free vars of ic_binds, and all the diff --git a/compiler/typecheck/TcUnify.hs b/compiler/typecheck/TcUnify.hs index 35f4d00f3981..45cc3f916849 100644 --- a/compiler/typecheck/TcUnify.hs +++ b/compiler/typecheck/TcUnify.hs @@ -64,6 +64,7 @@ import Util import qualified GHC.LanguageExtensions as LangExt import Outputable +import Data.Maybe( isNothing ) import Control.Monad import Control.Arrow ( second ) @@ -1176,7 +1177,13 @@ emitResidualTvConstraint :: SkolemInfo -> Maybe SDoc -> [TcTyVar] -> TcLevel -> WantedConstraints -> TcM () emitResidualTvConstraint skol_info m_telescope skol_tvs tclvl wanted | isEmptyWC wanted + , isNothing m_telescope || skol_tvs `lengthAtMost` 1 + -- If m_telescope is (Just d), we must do the bad-telescope check, + -- so we must /not/ discard the implication even if there are no + -- wanted constraints. See Note [Checking telescopes] in TcRnTypes. + -- Lacking this check led to #16247 = return () + | otherwise = do { ev_binds <- newNoTcEvBinds ; implic <- newImplication diff --git a/testsuite/tests/polykinds/T16247.hs b/testsuite/tests/polykinds/T16247.hs new file mode 100644 index 000000000000..617f3c4acae8 --- /dev/null +++ b/testsuite/tests/polykinds/T16247.hs @@ -0,0 +1,10 @@ +{-# LANGUAGE GADTs #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeInType #-} +module Bug where + +import Data.Kind + +data SameKind :: forall k. k -> k -> Type +data Foo :: forall a k (b :: k). SameKind a b -> Type where + MkFoo :: Foo sameKind diff --git a/testsuite/tests/polykinds/T16247.stderr b/testsuite/tests/polykinds/T16247.stderr new file mode 100644 index 000000000000..34a131999678 --- /dev/null +++ b/testsuite/tests/polykinds/T16247.stderr @@ -0,0 +1,7 @@ + +T16247.hs:9:13: error: + • These kind and type variables: a k (b :: k) + are out of dependency order. Perhaps try this ordering: + k (a :: k) (b :: k) + • In the kind ‘forall a k (b :: k). SameKind a b -> Type’ + In the data type declaration for ‘Foo’ diff --git a/testsuite/tests/polykinds/T16247a.hs b/testsuite/tests/polykinds/T16247a.hs new file mode 100644 index 000000000000..60a98d6c8f4e --- /dev/null +++ b/testsuite/tests/polykinds/T16247a.hs @@ -0,0 +1,23 @@ +{-# LANGUAGE ConstraintKinds #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeInType #-} +{-# LANGUAGE TypeOperators #-} +module Bug where + +import Data.Kind (Constraint, Type) +import GHC.Generics (Rep1, U1(..)) + +data TyFun :: Type -> Type -> Type +type a ~> b = TyFun a b -> Type +infixr 0 ~> +type family Apply (f :: a ~> b) (x :: a) :: b +type SameKind (a :: k) (b :: k) = (() :: Constraint) + +type family From1 (z :: (f :: Type -> Type) a) :: Rep1 f a + +type family From1U1 (x :: U1 (p :: k)) :: Rep1 U1 p where {} +data From1U1Sym0 :: forall p k. (U1 :: k -> Type) p ~> Rep1 (U1 :: k -> Type) p where + From1Sym0KindInference :: forall z arg. SameKind (Apply From1U1Sym0 arg) (From1U1 arg) + => From1U1Sym0 z diff --git a/testsuite/tests/polykinds/T16247a.stderr b/testsuite/tests/polykinds/T16247a.stderr new file mode 100644 index 000000000000..ce75878f389b --- /dev/null +++ b/testsuite/tests/polykinds/T16247a.stderr @@ -0,0 +1,8 @@ + +T16247a.hs:21:21: error: + • These kind and type variables: p k + are out of dependency order. Perhaps try this ordering: + k (p :: k) + • In the kind ‘forall p k. + (U1 :: k -> Type) p ~> Rep1 (U1 :: k -> Type) p’ + In the data type declaration for ‘From1U1Sym0’ diff --git a/testsuite/tests/polykinds/all.T b/testsuite/tests/polykinds/all.T index c67d80d621a0..6238fbe770a0 100644 --- a/testsuite/tests/polykinds/all.T +++ b/testsuite/tests/polykinds/all.T @@ -206,6 +206,8 @@ test('T14887a', normal, compile, ['']) test('T14847', normal, compile, ['']) test('T15795', normal, compile, ['']) test('T15795a', normal, compile, ['']) +test('T16247', normal, compile_fail, ['']) +test('T16247a', normal, compile_fail, ['']) test('KindVarOrder', normal, ghci_script, ['KindVarOrder.script']) test('T16221', normal, compile, ['']) test('T16221a', normal, compile_fail, ['']) -- GitLab