I recently noticed that building criterion-1.6.0.0 on GHC 7.10.3 or earlier using exceptions-0.10.6 will fail (example):
Failed to build criterion-1.6.0.0.
Build log ( /github/home/.cabal/logs/ghc-7.10.3/criterion-1.6.0.0-9cd2fd521a95b83c0fe29c1cf9fa357e9061f7e4f25468fdd4e13f93b10aa05f.log ):
Configuring library for criterion-1.6.0.0..
Preprocessing library for criterion-1.6.0.0..
Building library for criterion-1.6.0.0..
cabal-3.6.2.0: Failed to build criterion-1.6.0.0. See the build log above for details.
[ 1 of 13] Compiling Criterion.Main.Options.Internal ( Criterion/Main/Options/Internal.hs, dist/build/Criterion/Main/Options/Internal.o )
[ 2 of 13] Compiling Paths_criterion ( dist/build/autogen/Paths_criterion.hs, dist/build/Paths_criterion.o )
[ 3 of 13] Compiling Criterion.Types ( Criterion/Types.hs, dist/build/Criterion/Types.o )
[ 4 of 13] Compiling Criterion.Monad.Internal ( Criterion/Monad/Internal.hs, dist/build/Criterion/Monad/Internal.o )
Criterion/Monad/Internal.hs:40:18:
Non type-variable argument
in the constraint: ?callStack::GHC.Stack.CallStack
(Use FlexibleContexts to permit this)
In an expression type signature:
forall (e :: *)
(a :: *). (call-stack-0.4.0:Data.CallStack.HasCallStack,
GHC.Exception.Exception e) =>
e -> Criterion a
In the expression:
ghc-prim-0.4.0.0:GHC.Prim.coerce
(Control.Monad.Catch.throwM :: e -> ReaderT Crit IO a) ::
forall (e :: *)
(a :: *). (call-stack-0.4.0:Data.CallStack.HasCallStack,
GHC.Exception.Exception e) =>
e -> Criterion a
In an equation for ‘throwM’:
throwM
= ghc-prim-0.4.0.0:GHC.Prim.coerce
(Control.Monad.Catch.throwM :: e -> ReaderT Crit IO a) ::
forall (e :: *)
(a :: *). (call-stack-0.4.0:Data.CallStack.HasCallStack,
GHC.Exception.Exception e) =>
e -> Criterion a
When typechecking the code for ‘Control.Monad.Catch.throwM’
in a derived instance for ‘MonadThrow Criterion’:
To see the code I am typechecking, use -ddump-deriv
Criterion/Monad/Internal.hs:40:30:
Non type-variable argument
in the constraint: ?callStack::GHC.Stack.CallStack
(Use FlexibleContexts to permit this)
In an expression type signature:
forall (a :: *)
(e :: *). (call-stack-0.4.0:Data.CallStack.HasCallStack,
GHC.Exception.Exception e) =>
Criterion a -> (e -> Criterion a) -> Criterion a
In the expression:
ghc-prim-0.4.0.0:GHC.Prim.coerce
(Control.Monad.Catch.catch ::
ReaderT Crit IO a
-> (e -> ReaderT Crit IO a) -> ReaderT Crit IO a) ::
forall (a :: *)
(e :: *). (call-stack-0.4.0:Data.CallStack.HasCallStack,
GHC.Exception.Exception e) =>
Criterion a -> (e -> Criterion a) -> Criterion a
In an equation for ‘catch’:
catch
= ghc-prim-0.4.0.0:GHC.Prim.coerce
(Control.Monad.Catch.catch ::
ReaderT Crit IO a
-> (e -> ReaderT Crit IO a) -> ReaderT Crit IO a) ::
forall (a :: *)
(e :: *). (call-stack-0.4.0:Data.CallStack.HasCallStack,
GHC.Exception.Exception e) =>
Criterion a -> (e -> Criterion a) -> Criterion a
When typechecking the code for ‘Control.Monad.Catch.catch’
in a derived instance for ‘MonadCatch Criterion’:
To see the code I am typechecking, use -ddump-deriv
Criterion/Monad/Internal.hs:40:42:
Non type-variable argument
in the constraint: ?callStack::GHC.Stack.CallStack
(Use FlexibleContexts to permit this)
In an expression type signature:
forall (b :: *). call-stack-0.4.0:Data.CallStack.HasCallStack =>
((forall (a :: *). Criterion a -> Criterion a) -> Criterion b)
-> Criterion b
In the expression:
ghc-prim-0.4.0.0:GHC.Prim.coerce
(Control.Monad.Catch.mask ::
((forall (a :: *). ReaderT Crit IO a -> ReaderT Crit IO a)
-> ReaderT Crit IO b)
-> ReaderT Crit IO b) ::
forall (b :: *). call-stack-0.4.0:Data.CallStack.HasCallStack =>
((forall (a :: *). Criterion a -> Criterion a) -> Criterion b)
-> Criterion b
In an equation for ‘mask’:
mask
= ghc-prim-0.4.0.0:GHC.Prim.coerce
(Control.Monad.Catch.mask ::
((forall (a :: *). ReaderT Crit IO a -> ReaderT Crit IO a)
-> ReaderT Crit IO b)
-> ReaderT Crit IO b) ::
forall (b :: *). call-stack-0.4.0:Data.CallStack.HasCallStack =>
((forall (a :: *). Criterion a -> Criterion a) -> Criterion b)
-> Criterion b
When typechecking the code for ‘Control.Monad.Catch.mask’
in a derived instance for ‘MonadMask Criterion’:
To see the code I am typechecking, use -ddump-deriv
This is most likely an unforeseen consequence of using the call-stack library on pre-8.0 GHCs, which encodes the HasCallStack constraint differently than GHC 8.0+ does. While we could just insist that pre-8.0 GHCs should enable FlexibleContexts, this does (unfortunately) mean that the use of call-stack would be a breaking API change, and it feels silly to induce a breaking API change that only affects old GHC versions. Moreover, I'm unclear if call-stack's encoding of HasCallStack is even that functional on pre-8.0 GHCs.
In light of this, I think the most prudent course of action is to simply not use HasCallStack constraints at all on pre-8.0 GHCs. That is, do something like:
We would then use HasCallStack => ... constraints on all of the functions in exceptions. I'll work on making a new exceptions Hackage release with this change soon, and then we can deprecate exceptions-0.10.6.
I recently noticed that building
criterion-1.6.0.0
on GHC 7.10.3 or earlier usingexceptions-0.10.6
will fail (example):This is most likely an unforeseen consequence of using the
call-stack
library on pre-8.0 GHCs, which encodes theHasCallStack
constraint differently than GHC 8.0+ does. While we could just insist that pre-8.0 GHCs should enableFlexibleContexts
, this does (unfortunately) mean that the use ofcall-stack
would be a breaking API change, and it feels silly to induce a breaking API change that only affects old GHC versions. Moreover, I'm unclear ifcall-stack
's encoding ofHasCallStack
is even that functional on pre-8.0 GHCs.In light of this, I think the most prudent course of action is to simply not use
HasCallStack
constraints at all on pre-8.0 GHCs. That is, do something like:We would then use
HasCallStack => ...
constraints on all of the functions inexceptions
. I'll work on making a newexceptions
Hackage release with this change soon, and then we can deprecateexceptions-0.10.6
.