Commit c05fddde authored by elaforge's avatar elaforge Committed by Ben Gamari

Rearrange error msgs and add section markers (Trac #11014).

This puts the "Relevant bindings" section at the end.

It uses a TcErrors.Report Monoid to divide messages by importance and
then mappends them together.  This is not the most efficient way since
there are various intermediate Reports and list appends, but it probably
doesn't matter since error messages shouldn't get that large, and are
usually prepended.  In practice, everything is `important` except
`relevantBindings`, which is `supplementary`.

ErrMsg's errMsgShortDoc and errMsgExtraInfo were extracted into ErrDoc,
which has important, context, and suppelementary fields.  Each of those
three sections is marked with a bullet character, '•' on unicode
terminals and '*' on ascii terminals.  Since this breaks tons of tests,
I also modified testlib.normalise_errmsg to strip out '•'s.

--- Additional notes:

To avoid prepending * to an empty doc, I needed to filter empty docs.
This seemed less error-prone than trying to modify everyone who produces
SDoc to instead produce Maybe SDoc.  So I added `Outputable.isEmpty`.
Unfortunately it needs a DynFlags, which is kind of bogus, but otherwise
I think I'd need another Empty case for SDoc, and then it couldn't be a
newtype any more.

ErrMsg's errMsgShortString is only used by the Show instance, which is
in turn only used by Show HscTypes.SourceError, which is in turn only
needed for the Exception instance.  So it's probably possible to get rid
of errMsgShortString, but that would a be an unrelated cleanup.

Fixes #11014.

Test Plan: see above

Reviewers: austin, simonpj, thomie, bgamari

Reviewed By: thomie, bgamari

Subscribers: simonpj, nomeata, thomie

Differential Revision: https://phabricator.haskell.org/D1427

GHC Trac Issues: #11014
parent f09f2470
...@@ -25,7 +25,7 @@ import Util ...@@ -25,7 +25,7 @@ import Util
import DynFlags import DynFlags
import FastString import FastString
import Outputable import Outputable hiding ( isEmpty )
import qualified Data.Set as Set import qualified Data.Set as Set
import Control.Monad.Fix import Control.Monad.Fix
import Data.Array as Array import Data.Array as Array
......
...@@ -10,14 +10,15 @@ module ErrUtils ( ...@@ -10,14 +10,15 @@ module ErrUtils (
MsgDoc, MsgDoc,
Validity(..), andValid, allValid, isValid, getInvalids, Validity(..), andValid, allValid, isValid, getInvalids,
ErrMsg, WarnMsg, Severity(..), ErrMsg, ErrDoc, errDoc, WarnMsg, Severity(..),
Messages, ErrorMessages, WarningMessages, Messages, ErrorMessages, WarningMessages,
errMsgSpan, errMsgContext, errMsgShortDoc, errMsgExtraInfo, errMsgSpan, errMsgContext,
mkLocMessage, pprMessageBag, pprErrMsgBagWithLoc, mkLocMessage, pprMessageBag, pprErrMsgBagWithLoc,
pprLocErrMsg, makeIntoWarning, pprLocErrMsg, makeIntoWarning,
errorsFound, emptyMessages, isEmptyMessages, errorsFound, emptyMessages, isEmptyMessages,
mkErrMsg, mkPlainErrMsg, mkLongErrMsg, mkWarnMsg, mkPlainWarnMsg, mkErrMsg, mkPlainErrMsg, mkErrDoc, mkLongErrMsg, mkWarnMsg,
mkPlainWarnMsg,
printBagOfErrors, printBagOfErrors,
warnIsErrorMsg, mkLongWarnMsg, warnIsErrorMsg, mkLongWarnMsg,
...@@ -94,13 +95,28 @@ type ErrorMessages = Bag ErrMsg ...@@ -94,13 +95,28 @@ type ErrorMessages = Bag ErrMsg
data ErrMsg = ErrMsg { data ErrMsg = ErrMsg {
errMsgSpan :: SrcSpan, errMsgSpan :: SrcSpan,
errMsgContext :: PrintUnqualified, errMsgContext :: PrintUnqualified,
errMsgShortDoc :: MsgDoc, -- errMsgShort* should always errMsgDoc :: ErrDoc,
errMsgShortString :: String, -- contain the same text -- | This has the same text as errDocImportant . errMsgDoc.
errMsgExtraInfo :: MsgDoc, errMsgShortString :: String,
errMsgSeverity :: Severity errMsgSeverity :: Severity
} }
-- The SrcSpan is used for sorting errors into line-number order -- The SrcSpan is used for sorting errors into line-number order
-- | Categorise error msgs by their importance. This is so each section can
-- be rendered visually distinct. See Note [Error report] for where these come
-- from.
data ErrDoc = ErrDoc {
-- | Primary error msg.
errDocImportant :: [MsgDoc],
-- | Context e.g. \"In the second argument of ...\".
_errDocContext :: [MsgDoc],
-- | Supplementary information, e.g. \"Relevant bindings include ...\".
_errDocSupplementary :: [MsgDoc]
}
errDoc :: [MsgDoc] -> [MsgDoc] -> [MsgDoc] -> ErrDoc
errDoc = ErrDoc
type WarnMsg = ErrMsg type WarnMsg = ErrMsg
data Severity data Severity
...@@ -156,13 +172,17 @@ makeIntoWarning err = err { errMsgSeverity = SevWarning } ...@@ -156,13 +172,17 @@ makeIntoWarning err = err { errMsgSeverity = SevWarning }
-- ----------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
-- Collecting up messages for later ordering and printing. -- Collecting up messages for later ordering and printing.
mk_err_msg :: DynFlags -> Severity -> SrcSpan -> PrintUnqualified -> MsgDoc -> SDoc -> ErrMsg mk_err_msg :: DynFlags -> Severity -> SrcSpan -> PrintUnqualified -> ErrDoc -> ErrMsg
mk_err_msg dflags sev locn print_unqual msg extra mk_err_msg dflags sev locn print_unqual doc
= ErrMsg { errMsgSpan = locn, errMsgContext = print_unqual = ErrMsg { errMsgSpan = locn
, errMsgShortDoc = msg , errMsgShortString = showSDoc dflags msg , errMsgContext = print_unqual
, errMsgExtraInfo = extra , errMsgDoc = doc
, errMsgShortString = showSDoc dflags (vcat (errDocImportant doc))
, errMsgSeverity = sev } , errMsgSeverity = sev }
mkErrDoc :: DynFlags -> SrcSpan -> PrintUnqualified -> ErrDoc -> ErrMsg
mkErrDoc dflags = mk_err_msg dflags SevError
mkLongErrMsg, mkLongWarnMsg :: DynFlags -> SrcSpan -> PrintUnqualified -> MsgDoc -> MsgDoc -> ErrMsg mkLongErrMsg, mkLongWarnMsg :: DynFlags -> SrcSpan -> PrintUnqualified -> MsgDoc -> MsgDoc -> ErrMsg
-- A long (multi-line) error message -- A long (multi-line) error message
mkErrMsg, mkWarnMsg :: DynFlags -> SrcSpan -> PrintUnqualified -> MsgDoc -> ErrMsg mkErrMsg, mkWarnMsg :: DynFlags -> SrcSpan -> PrintUnqualified -> MsgDoc -> ErrMsg
...@@ -170,12 +190,12 @@ mkErrMsg, mkWarnMsg :: DynFlags -> SrcSpan -> PrintUnqualified -> MsgD ...@@ -170,12 +190,12 @@ mkErrMsg, mkWarnMsg :: DynFlags -> SrcSpan -> PrintUnqualified -> MsgD
mkPlainErrMsg, mkPlainWarnMsg :: DynFlags -> SrcSpan -> MsgDoc -> ErrMsg mkPlainErrMsg, mkPlainWarnMsg :: DynFlags -> SrcSpan -> MsgDoc -> ErrMsg
-- Variant that doesn't care about qualified/unqualified names -- Variant that doesn't care about qualified/unqualified names
mkLongErrMsg dflags locn unqual msg extra = mk_err_msg dflags SevError locn unqual msg extra mkLongErrMsg dflags locn unqual msg extra = mk_err_msg dflags SevError locn unqual (ErrDoc [msg] [] [extra])
mkErrMsg dflags locn unqual msg = mk_err_msg dflags SevError locn unqual msg empty mkErrMsg dflags locn unqual msg = mk_err_msg dflags SevError locn unqual (ErrDoc [msg] [] [])
mkPlainErrMsg dflags locn msg = mk_err_msg dflags SevError locn alwaysQualify msg empty mkPlainErrMsg dflags locn msg = mk_err_msg dflags SevError locn alwaysQualify (ErrDoc [msg] [] [])
mkLongWarnMsg dflags locn unqual msg extra = mk_err_msg dflags SevWarning locn unqual msg extra mkLongWarnMsg dflags locn unqual msg extra = mk_err_msg dflags SevWarning locn unqual (ErrDoc [msg] [] [extra])
mkWarnMsg dflags locn unqual msg = mk_err_msg dflags SevWarning locn unqual msg empty mkWarnMsg dflags locn unqual msg = mk_err_msg dflags SevWarning locn unqual (ErrDoc [msg] [] [])
mkPlainWarnMsg dflags locn msg = mk_err_msg dflags SevWarning locn alwaysQualify msg empty mkPlainWarnMsg dflags locn msg = mk_err_msg dflags SevWarning locn alwaysQualify (ErrDoc [msg] [] [])
---------------- ----------------
emptyMessages :: Messages emptyMessages :: Messages
...@@ -194,34 +214,42 @@ errorsFound _dflags (_warns, errs) = not (isEmptyBag errs) ...@@ -194,34 +214,42 @@ errorsFound _dflags (_warns, errs) = not (isEmptyBag errs)
printBagOfErrors :: DynFlags -> Bag ErrMsg -> IO () printBagOfErrors :: DynFlags -> Bag ErrMsg -> IO ()
printBagOfErrors dflags bag_of_errors printBagOfErrors dflags bag_of_errors
= sequence_ [ let style = mkErrStyle dflags unqual = sequence_ [ let style = mkErrStyle dflags unqual
in log_action dflags dflags sev s style (d $$ e) in log_action dflags dflags sev s style (formatErrDoc dflags doc)
| ErrMsg { errMsgSpan = s, | ErrMsg { errMsgSpan = s,
errMsgShortDoc = d, errMsgDoc = doc,
errMsgSeverity = sev, errMsgSeverity = sev,
errMsgExtraInfo = e,
errMsgContext = unqual } <- sortMsgBag (Just dflags) errMsgContext = unqual } <- sortMsgBag (Just dflags)
bag_of_errors bag_of_errors ]
]
formatErrDoc :: DynFlags -> ErrDoc -> SDoc
formatErrDoc dflags (ErrDoc important context supplementary)
= case msgs of
[msg] -> vcat msg
_ -> vcat $ map starred msgs
where
msgs = filter (not . null) $ map (filter (not . Outputable.isEmpty dflags))
[important, context, supplementary]
starred = (bullet<+>) . vcat
bullet = text $ if DynFlags.useUnicode dflags then "•" else "*"
pprErrMsgBagWithLoc :: Bag ErrMsg -> [SDoc] pprErrMsgBagWithLoc :: Bag ErrMsg -> [SDoc]
pprErrMsgBagWithLoc bag = [ pprLocErrMsg item | item <- sortMsgBag Nothing bag ] pprErrMsgBagWithLoc bag = [ pprLocErrMsg item | item <- sortMsgBag Nothing bag ]
pprLocErrMsg :: ErrMsg -> SDoc pprLocErrMsg :: ErrMsg -> SDoc
pprLocErrMsg (ErrMsg { errMsgSpan = s pprLocErrMsg (ErrMsg { errMsgSpan = s
, errMsgShortDoc = d , errMsgDoc = doc
, errMsgExtraInfo = e
, errMsgSeverity = sev , errMsgSeverity = sev
, errMsgContext = unqual }) , errMsgContext = unqual })
= sdocWithDynFlags $ \dflags -> = sdocWithDynFlags $ \dflags ->
withPprStyle (mkErrStyle dflags unqual) $ withPprStyle (mkErrStyle dflags unqual) $
mkLocMessage sev s (d $$ e) mkLocMessage sev s (formatErrDoc dflags doc)
sortMsgBag :: Maybe DynFlags -> Bag ErrMsg -> [ErrMsg] sortMsgBag :: Maybe DynFlags -> Bag ErrMsg -> [ErrMsg]
sortMsgBag dflags = sortBy (maybeFlip $ comparing errMsgSpan) . bagToList sortMsgBag dflags = sortBy (maybeFlip $ comparing errMsgSpan) . bagToList
where maybeFlip :: (a -> a -> b) -> (a -> a -> b) where maybeFlip :: (a -> a -> b) -> (a -> a -> b)
maybeFlip maybeFlip
| fromMaybe False (fmap reverseErrors dflags) = flip | fromMaybe False (fmap reverseErrors dflags) = flip
| otherwise = id | otherwise = id
ghcExit :: DynFlags -> Int -> IO () ghcExit :: DynFlags -> Int -> IO ()
ghcExit dflags val ghcExit dflags val
......
This diff is collapsed.
...@@ -753,6 +753,12 @@ mkLongErrAt loc msg extra ...@@ -753,6 +753,12 @@ mkLongErrAt loc msg extra
printer <- getPrintUnqualified dflags ; printer <- getPrintUnqualified dflags ;
return $ mkLongErrMsg dflags loc printer msg extra } return $ mkLongErrMsg dflags loc printer msg extra }
mkErrDocAt :: SrcSpan -> ErrDoc -> TcRn ErrMsg
mkErrDocAt loc errDoc
= do { dflags <- getDynFlags ;
printer <- getPrintUnqualified dflags ;
return $ mkErrDoc dflags loc printer errDoc }
addLongErrAt :: SrcSpan -> MsgDoc -> MsgDoc -> TcRn () addLongErrAt :: SrcSpan -> MsgDoc -> MsgDoc -> TcRn ()
addLongErrAt loc msg extra = mkLongErrAt loc msg extra >>= reportError addLongErrAt loc msg extra = mkLongErrAt loc msg extra >>= reportError
...@@ -769,7 +775,7 @@ reportError err ...@@ -769,7 +775,7 @@ reportError err
reportWarning :: ErrMsg -> TcRn () reportWarning :: ErrMsg -> TcRn ()
reportWarning err reportWarning err
= do { let warn = makeIntoWarning err = do { let warn = makeIntoWarning err
-- 'err' was build by mkLongErrMsg or something like that, -- 'err' was built by mkLongErrMsg or something like that,
-- so it's of error severity. For a warning we downgrade -- so it's of error severity. For a warning we downgrade
-- its severity to SevWarning -- its severity to SevWarning
...@@ -1099,7 +1105,7 @@ mkErrInfo env ctxts ...@@ -1099,7 +1105,7 @@ mkErrInfo env ctxts
= go 0 env ctxts = go 0 env ctxts
where where
go :: Int -> TidyEnv -> [ErrCtxt] -> TcM SDoc go :: Int -> TidyEnv -> [ErrCtxt] -> TcM SDoc
go _ _ [] = return Outputable.empty go _ _ [] = return empty
go n env ((is_landmark, ctxt) : ctxts) go n env ((is_landmark, ctxt) : ctxts)
| is_landmark || n < mAX_CONTEXTS -- Too verbose || opt_PprStyle_Debug | is_landmark || n < mAX_CONTEXTS -- Too verbose || opt_PprStyle_Debug
= do { (env', msg) <- ctxt env = do { (env', msg) <- ctxt env
......
...@@ -19,7 +19,7 @@ module Outputable ( ...@@ -19,7 +19,7 @@ module Outputable (
docToSDoc, docToSDoc,
interppSP, interpp'SP, interppSP, interpp'SP,
pprQuotedList, pprWithCommas, quotedListWithOr, quotedListWithNor, pprQuotedList, pprWithCommas, quotedListWithOr, quotedListWithNor,
empty, nest, empty, isEmpty, nest,
char, char,
text, ftext, ptext, ztext, text, ftext, ptext, ztext,
int, intWithCommas, integer, float, double, rational, int, intWithCommas, integer, float, double, rational,
...@@ -301,8 +301,8 @@ pprDeeper d = SDoc $ \ctx -> case ctx of ...@@ -301,8 +301,8 @@ pprDeeper d = SDoc $ \ctx -> case ctx of
runSDoc d ctx{sdocStyle = PprUser q (PartWay (n-1))} runSDoc d ctx{sdocStyle = PprUser q (PartWay (n-1))}
_ -> runSDoc d ctx _ -> runSDoc d ctx
-- | Truncate a list that is longer than the current depth.
pprDeeperList :: ([SDoc] -> SDoc) -> [SDoc] -> SDoc pprDeeperList :: ([SDoc] -> SDoc) -> [SDoc] -> SDoc
-- Truncate a list that list that is longer than the current depth
pprDeeperList f ds pprDeeperList f ds
| null ds = f [] | null ds = f []
| otherwise = SDoc work | otherwise = SDoc work
...@@ -462,6 +462,10 @@ irrelevantNCols :: Int ...@@ -462,6 +462,10 @@ irrelevantNCols :: Int
-- Used for OneLineMode and LeftMode when number of cols isn't used -- Used for OneLineMode and LeftMode when number of cols isn't used
irrelevantNCols = 1 irrelevantNCols = 1
isEmpty :: DynFlags -> SDoc -> Bool
isEmpty dflags sdoc = Pretty.isEmpty $ runSDoc sdoc dummySDocContext
where dummySDocContext = initSDocContext dflags PprDebug
docToSDoc :: Doc -> SDoc docToSDoc :: Doc -> SDoc
docToSDoc d = SDoc (\_ -> d) docToSDoc d = SDoc (\_ -> d)
......
# coding=utf8
# #
# (c) Simon Marlow 2002 # (c) Simon Marlow 2002
# #
...@@ -1547,7 +1548,8 @@ def check_stderr_ok(name, way): ...@@ -1547,7 +1548,8 @@ def check_stderr_ok(name, way):
return compare_outputs(way, 'stderr', return compare_outputs(way, 'stderr',
join_normalisers(norm, getTestOpts().extra_errmsg_normaliser), \ join_normalisers(norm, getTestOpts().extra_errmsg_normaliser), \
expected_stderr_file, actual_stderr_file) expected_stderr_file, actual_stderr_file,
whitespace_normaliser=normalise_whitespace)
def dump_stderr( name ): def dump_stderr( name ):
print("Stderr:") print("Stderr:")
...@@ -1692,8 +1694,7 @@ def compare_outputs(way, kind, normaliser, expected_file, actual_file, ...@@ -1692,8 +1694,7 @@ def compare_outputs(way, kind, normaliser, expected_file, actual_file,
def normalise_whitespace( str ): def normalise_whitespace( str ):
# Merge contiguous whitespace characters into a single space. # Merge contiguous whitespace characters into a single space.
str = re.sub('[ \t\n]+', ' ', str) return ' '.join(w for w in str.split())
return str.strip()
def normalise_callstacks(str): def normalise_callstacks(str):
def repl(matches): def repl(matches):
...@@ -1722,6 +1723,11 @@ def normalise_errmsg( str ): ...@@ -1722,6 +1723,11 @@ def normalise_errmsg( str ):
str = re.sub('ghc-stage[123]', 'ghc', str) str = re.sub('ghc-stage[123]', 'ghc', str)
# Error messages simetimes contain integer implementation package # Error messages simetimes contain integer implementation package
str = re.sub('integer-(gmp|simple)-[0-9.]+', 'integer-<IMPL>-<VERSION>', str) str = re.sub('integer-(gmp|simple)-[0-9.]+', 'integer-<IMPL>-<VERSION>', str)
# Also filter out bullet characters. This is because bullets are used to
# separate error sections, and tests shouldn't be sensitive to how the
# the division happens.
bullet = u'•'.encode('utf8')
str = str.replace(bullet, '')
return str return str
# normalise a .prof file, so that we can reasonably compare it against # normalise a .prof file, so that we can reasonably compare it against
......
...@@ -5,12 +5,12 @@ T5380.hs:7:27: ...@@ -5,12 +5,12 @@ T5380.hs:7:27:
the type signature for: the type signature for:
testB :: not_bool -> (() -> ()) -> () -> not_unit testB :: not_bool -> (() -> ()) -> () -> not_unit
at T5380.hs:6:10 at T5380.hs:6:10
In the expression: b
In the expression: proc () -> if b then f -< () else f -< ()
Relevant bindings include Relevant bindings include
b :: not_bool (bound at T5380.hs:7:7) b :: not_bool (bound at T5380.hs:7:7)
testB :: not_bool -> (() -> ()) -> () -> not_unit testB :: not_bool -> (() -> ()) -> () -> not_unit
(bound at T5380.hs:7:1) (bound at T5380.hs:7:1)
In the expression: b
In the expression: proc () -> if b then f -< () else f -< ()
T5380.hs:7:34: T5380.hs:7:34:
Couldn't match type ‘not_unit’ with ‘()’ Couldn't match type ‘not_unit’ with ‘()’
...@@ -20,8 +20,8 @@ T5380.hs:7:34: ...@@ -20,8 +20,8 @@ T5380.hs:7:34:
at T5380.hs:6:10 at T5380.hs:6:10
Expected type: () -> not_unit Expected type: () -> not_unit
Actual type: () -> () Actual type: () -> ()
In the expression: f
In the command: f -< ()
Relevant bindings include Relevant bindings include
testB :: not_bool -> (() -> ()) -> () -> not_unit testB :: not_bool -> (() -> ()) -> () -> not_unit
(bound at T5380.hs:7:1) (bound at T5380.hs:7:1)
In the expression: f
In the command: f -< ()
T2507.hs:5:7: error: T2507.hs:5:7: error:
Couldn't match expected type `Int' with actual type `()' * Couldn't match expected type `Int' with actual type `()'
In the expression: () * In the expression: ()
In an equation for `foo': foo = () In an equation for `foo': foo = ()
T6037.hs:5:7: T6037.hs:5:7:
Couldn't match expected type `Int' with actual type `()' * Couldn't match expected type `Int' with actual type `()'
In the expression: () * In the expression: ()
In an equation for `f?o': f?o = () In an equation for `f?o': f?o = ()
T8959a.hs:5:7: error: T8959a.hs:5:7: error:
Couldn't match expected type `Int -> Int' with actual type `()' * Couldn't match expected type `Int -> Int' with actual type `()'
In the expression: () * In the expression: ()
In an equation for `foo': foo = () In an equation for `foo': foo = ()
...@@ -7,10 +7,10 @@ T3169.hs:13:22: ...@@ -7,10 +7,10 @@ T3169.hs:13:22:
at T3169.hs:12:3 at T3169.hs:12:3
Expected type: Map a (Map b elt) Expected type: Map a (Map b elt)
Actual type: Map (a, b) elt Actual type: Map (a, b) elt
In the second argument of ‘lookup’, namely ‘m’
In the expression: lookup a m :: Maybe (Map b elt)
Relevant bindings include Relevant bindings include
m :: Map (a, b) elt (bound at T3169.hs:12:17) m :: Map (a, b) elt (bound at T3169.hs:12:17)
b :: b (bound at T3169.hs:12:13) b :: b (bound at T3169.hs:12:13)
lookup :: (a, b) -> Map (a, b) elt -> Maybe elt lookup :: (a, b) -> Map (a, b) elt -> Maybe elt
(bound at T3169.hs:12:3) (bound at T3169.hs:12:3)
In the second argument of ‘lookup’, namely ‘m’
In the expression: lookup a m :: Maybe (Map b elt)
...@@ -7,7 +7,7 @@ T7558.hs:8:4: ...@@ -7,7 +7,7 @@ T7558.hs:8:4:
a pattern with constructor: a pattern with constructor:
MkT :: forall a b. (a ~ Maybe b) => a -> Maybe b -> T a b, MkT :: forall a b. (a ~ Maybe b) => a -> Maybe b -> T a b,
in an equation for ‘f’ in an equation for ‘f’
Relevant bindings include
f :: T a a -> Bool (bound at T7558.hs:8:1)
In the pattern: MkT x y In the pattern: MkT x y
In an equation for ‘f’: f (MkT x y) = [x, y] `seq` True In an equation for ‘f’: f (MkT x y) = [x, y] `seq` True
Relevant bindings include
f :: T a a -> Bool (bound at T7558.hs:8:1)
...@@ -11,7 +11,7 @@ gadt-escape1.hs:19:58: ...@@ -11,7 +11,7 @@ gadt-escape1.hs:19:58:
Possible fix: add a type signature for ‘weird1’ Possible fix: add a type signature for ‘weird1’
Expected type: t Expected type: t
Actual type: ExpGADT t1 Actual type: ExpGADT t1
Relevant bindings include
weird1 :: t (bound at gadt-escape1.hs:19:1)
In the expression: a In the expression: a
In a case alternative: Hidden (ExpInt _) a -> a In a case alternative: Hidden (ExpInt _) a -> a
Relevant bindings include
weird1 :: t (bound at gadt-escape1.hs:19:1)
...@@ -10,7 +10,7 @@ gadt13.hs:15:13: ...@@ -10,7 +10,7 @@ gadt13.hs:15:13:
‘t’ is a rigid type variable bound by ‘t’ is a rigid type variable bound by
the inferred type of shw :: Term t1 -> t at gadt13.hs:15:1 the inferred type of shw :: Term t1 -> t at gadt13.hs:15:1
Possible fix: add a type signature for ‘shw’ Possible fix: add a type signature for ‘shw’
Relevant bindings include
shw :: Term t1 -> t (bound at gadt13.hs:15:1)
In the expression: ("I " ++) . shows t In the expression: ("I " ++) . shows t
In an equation for ‘shw’: shw (I t) = ("I " ++) . shows t In an equation for ‘shw’: shw (I t) = ("I " ++) . shows t
Relevant bindings include
shw :: Term t1 -> t (bound at gadt13.hs:15:1)
...@@ -11,9 +11,9 @@ gadt7.hs:16:38: ...@@ -11,9 +11,9 @@ gadt7.hs:16:38:
‘t’ is a rigid type variable bound by ‘t’ is a rigid type variable bound by
the inferred type of i1b :: T t1 -> r -> t at gadt7.hs:16:1 the inferred type of i1b :: T t1 -> r -> t at gadt7.hs:16:1
Possible fix: add a type signature for ‘i1b’ Possible fix: add a type signature for ‘i1b’
In the expression: y1
In a case alternative: K -> y1
Relevant bindings include Relevant bindings include
y1 :: r (bound at gadt7.hs:16:16) y1 :: r (bound at gadt7.hs:16:16)
y :: r (bound at gadt7.hs:16:7) y :: r (bound at gadt7.hs:16:7)
i1b :: T t1 -> r -> t (bound at gadt7.hs:16:1) i1b :: T t1 -> r -> t (bound at gadt7.hs:16:1)
In the expression: y1
In a case alternative: K -> y1
...@@ -4,13 +4,13 @@ rw.hs:14:47: ...@@ -4,13 +4,13 @@ rw.hs:14:47:
‘a’ is a rigid type variable bound by ‘a’ is a rigid type variable bound by
the type signature for: writeInt :: T a -> IORef a -> IO () the type signature for: writeInt :: T a -> IORef a -> IO ()
at rw.hs:12:12 at rw.hs:12:12
In the second argument of ‘writeIORef’, namely ‘(1 :: Int)’
In the expression: writeIORef ref (1 :: Int)
In a case alternative: ~(Li x) -> writeIORef ref (1 :: Int)
Relevant bindings include Relevant bindings include
ref :: IORef a (bound at rw.hs:13:12) ref :: IORef a (bound at rw.hs:13:12)
v :: T a (bound at rw.hs:13:10) v :: T a (bound at rw.hs:13:10)
writeInt :: T a -> IORef a -> IO () (bound at rw.hs:13:1) writeInt :: T a -> IORef a -> IO () (bound at rw.hs:13:1)
In the second argument of ‘writeIORef’, namely ‘(1 :: Int)’
In the expression: writeIORef ref (1 :: Int)
In a case alternative: ~(Li x) -> writeIORef ref (1 :: Int)
rw.hs:19:51: rw.hs:19:51:
Couldn't match type ‘a’ with ‘Bool’ Couldn't match type ‘a’ with ‘Bool’
...@@ -19,9 +19,9 @@ rw.hs:19:51: ...@@ -19,9 +19,9 @@ rw.hs:19:51:
at rw.hs:16:12 at rw.hs:16:12
Expected type: a -> Bool Expected type: a -> Bool
Actual type: Bool -> Bool Actual type: Bool -> Bool
In the second argument of ‘(.)’, namely ‘not’
In the second argument of ‘(>>=)’, namely ‘(print . not)’
Relevant bindings include Relevant bindings include
ref :: IORef a (bound at rw.hs:17:12) ref :: IORef a (bound at rw.hs:17:12)
v :: T a (bound at rw.hs:17:10) v :: T a (bound at rw.hs:17:10)
readBool :: T a -> IORef a -> IO () (bound at rw.hs:17:1) readBool :: T a -> IORef a -> IO () (bound at rw.hs:17:1)
In the second argument of ‘(.)’, namely ‘not’
In the second argument of ‘(>>=)’, namely ‘(print . not)’
...@@ -33,12 +33,12 @@ ...@@ -33,12 +33,12 @@
../../typecheck/should_run/Defer01.hs:31:5: warning: ../../typecheck/should_run/Defer01.hs:31:5: warning:
Couldn't match expected type ‘Char -> t’ with actual type ‘Char’ Couldn't match expected type ‘Char -> t’ with actual type ‘Char’
Relevant bindings include
f :: t (bound at ../../typecheck/should_run/Defer01.hs:31:1)
The function ‘e’ is applied to one argument, The function ‘e’ is applied to one argument,
but its type ‘Char’ has none but its type ‘Char’ has none
In the expression: e 'q' In the expression: e 'q'
In an equation for ‘f’: f = e 'q' In an equation for ‘f’: f = e 'q'
Relevant bindings include
f :: t (bound at ../../typecheck/should_run/Defer01.hs:31:1)
../../typecheck/should_run/Defer01.hs:34:8: warning: ../../typecheck/should_run/Defer01.hs:34:8: warning:
Couldn't match expected type ‘Char’ with actual type ‘a’ Couldn't match expected type ‘Char’ with actual type ‘a’
...@@ -46,20 +46,20 @@ ...@@ -46,20 +46,20 @@
the type signature for: the type signature for:
h :: a -> (Char, Char) h :: a -> (Char, Char)
at ../../typecheck/should_run/Defer01.hs:33:6 at ../../typecheck/should_run/Defer01.hs:33:6
In the expression: x
In the expression: (x, 'c')
Relevant bindings include Relevant bindings include
x :: a (bound at ../../typecheck/should_run/Defer01.hs:34:3) x :: a (bound at ../../typecheck/should_run/Defer01.hs:34:3)
h :: a -> (Char, Char) h :: a -> (Char, Char)
(bound at ../../typecheck/should_run/Defer01.hs:34:1) (bound at ../../typecheck/should_run/Defer01.hs:34:1)
In the expression: x
In the expression: (x, 'c')
../../typecheck/should_run/Defer01.hs:39:17: warning: ../../typecheck/should_run/Defer01.hs:39:17: warning:
Couldn't match expected type ‘Bool’ with actual type ‘T a’ Couldn't match expected type ‘Bool’ with actual type ‘T a’
In the first argument of ‘not’, namely ‘(K a)’
In the expression: (not (K a))
Relevant bindings include Relevant bindings include
a :: a (bound at ../../typecheck/should_run/Defer01.hs:39:3) a :: a (bound at ../../typecheck/should_run/Defer01.hs:39:3)
i :: a -> () (bound at ../../typecheck/should_run/Defer01.hs:39:1) i :: a -> () (bound at ../../typecheck/should_run/Defer01.hs:39:1)
In the first argument of ‘not’, namely ‘(K a)’
In the expression: (not (K a))
../../typecheck/should_run/Defer01.hs:43:5: warning: ../../typecheck/should_run/Defer01.hs:43:5: warning:
No instance for (MyClass a1) arising from a use of ‘myOp’ No instance for (MyClass a1) arising from a use of ‘myOp’
...@@ -147,12 +147,12 @@ ...@@ -147,12 +147,12 @@
(deferred type error) (deferred type error)
*** Exception: ../../typecheck/should_run/Defer01.hs:31:5: error: *** Exception: ../../typecheck/should_run/Defer01.hs:31:5: error:
Couldn't match expected type ‘Char -> t’ with actual type ‘Char’ Couldn't match expected type ‘Char -> t’ with actual type ‘Char’
Relevant bindings include
f :: t (bound at ../../typecheck/should_run/Defer01.hs:31:1)
The function ‘e’ is applied to one argument, The function ‘e’ is applied to one argument,
but its type ‘Char’ has none but its type ‘Char’ has none
In the expression: e 'q' In the expression: e 'q'
In an equation for ‘f’: f = e 'q' In an equation for ‘f’: f = e 'q'
Relevant bindings include
f :: t (bound at ../../typecheck/should_run/Defer01.hs:31:1)
(deferred type error) (deferred type error)
*** Exception: ../../typecheck/should_run/Defer01.hs:34:8: error: *** Exception: ../../typecheck/should_run/Defer01.hs:34:8: error:
Couldn't match expected type ‘Char’ with actual type ‘a’ Couldn't match expected type ‘Char’ with actual type ‘a’
...@@ -160,20 +160,20 @@ ...@@ -160,20 +160,20 @@
the type signature for: the type signature for:
h :: a -> (Char, Char) h :: a -> (Char, Char)
at ../../typecheck/should_run/Defer01.hs:33:6 at ../../typecheck/should_run/Defer01.hs:33:6
In the expression: x
In the expression: (x, 'c')
Relevant bindings include Relevant bindings include
x :: a (bound at ../../typecheck/should_run/Defer01.hs:34:3) x :: a (bound at ../../typecheck/should_run/Defer01.hs:34:3)
h :: a -> (Char, Char) h :: a -> (Char, Char)
(bound at ../../typecheck/should_run/Defer01.hs:34:1) (bound at ../../typecheck/should_run/Defer01.hs:34:1)
In the expression: x
In the expression: (x, 'c')
(deferred type error) (deferred type error)
*** Exception: ../../typecheck/should_run/Defer01.hs:39:17: error: *** Exception: ../../typecheck/should_run/Defer01.hs:39:17: error:
Couldn't match expected type ‘Bool’ with actual type ‘T a’ Couldn't match expected type ‘Bool’ with actual type ‘T a’
In the first argument of ‘not’, namely ‘(K a)’