Commit 1c920832 authored by Matthías Páll Gissurarson's avatar Matthías Páll Gissurarson Committed by Ben Gamari

Also show types that subsume a hole as valid substitutions for that hole.

This builds on the previous "Valid substitutions include..." functionality,
but add subsumption checking as well, so that the suggested valid substitutions
show not only exact matches, but also identifiers that fit the hole by virtue of
subsuming the type of the hole (i.e. being more general than the type of the
hole).

Building on the previous example, in the given program

```
ps :: String -> IO ()
ps = putStrLn

ps2 :: a -> IO ()
ps2 _ = putStrLn "hello, world"

main :: IO ()
main = _ "hello, world"
```

The results would be something like

```
    • Found hole: _ :: [Char] -> IO ()
    • In the expression: _
      In the expression: _ "hello, world"
      In an equation for ‘main’: main = _ "hello, world"
    • Relevant bindings include main :: IO () (bound at t1.hs:8:1)
      Valid substitutions include
        ps :: String -> IO () (defined at t1.hs:2:1)
        ps2 :: forall a. a -> IO () (defined at t1.hs:5:1)
        putStrLn :: String -> IO ()
          (imported from ‘Prelude’ at t1.hs:1:1
           (and originally defined in ‘System.IO’))
        fail :: forall (m :: * -> *). Monad m => forall a. String -> m a
          (imported from ‘Prelude’ at t1.hs:1:1
           (and originally defined in ‘GHC.Base’))
        mempty :: forall a. Monoid a => a
          (imported from ‘Prelude’ at t1.hs:1:1
           (and originally defined in ‘GHC.Base’))
        print :: forall a. Show a => a -> IO ()
          (imported from ‘Prelude’ at t1.hs:1:1
           (and originally defined in ‘System.IO’))
        (Some substitutions suppressed;
         use -fmax-valid-substitutions=N or -fno-max-valid-substitutions)
```
Signed-off-by: Matthías Páll Gissurarson's avatarMatthías Páll Gissurarson <mpg@mpg.is>

Modified according to suggestions from Simon PJ

Accept tests that match the expectations, still a few to look better at

Swithced to using tcLookup, after sit down with SPJ at ICFP. Implications are WIP.

Now works with polymorphism and constraints!

We still need to merge the latest master, before we can make a patch.

Wrap the type of the hole, instead of implication shenanigans,

As per SPJs suggestion, this is simpler and feels closer to
what we actually want to do.

Updated tests with the new implementation

Remove debugging trace and update documentation

Reviewers: austin, bgamari

Reviewed By: bgamari

Subscribers: RyanGlScott, rwbarton, thomie

Differential Revision: https://phabricator.haskell.org/D3930
parent 063e0b4e
......@@ -34,7 +34,7 @@ module TcEnv(
isTypeClosedLetBndr,
tcLookup, tcLookupLocated, tcLookupLocalIds,
tcLookupId, tcLookupTyVar,
tcLookupId, tcLookupIdMaybe, tcLookupTyVar,
tcLookupLcl_maybe,
getInLocalScope,
wrongThingErr, pprBinders,
......@@ -352,11 +352,18 @@ tcLookupId :: Name -> TcM Id
--
-- The Id is never a DataCon. (Why does that matter? see TcExpr.tcId)
tcLookupId name = do
thing <- tcLookup name
thing <- tcLookupIdMaybe name
case thing of
ATcId { tct_id = id} -> return id
AGlobal (AnId id) -> return id
_ -> pprPanic "tcLookupId" (ppr name)
Just id -> return id
_ -> pprPanic "tcLookupId" (ppr name)
tcLookupIdMaybe :: Name -> TcM (Maybe Id)
tcLookupIdMaybe name
= do { thing <- tcLookup name
; case thing of
ATcId { tct_id = id} -> return $ Just id
AGlobal (AnId id) -> return $ Just id
_ -> return Nothing }
tcLookupLocalIds :: [Name] -> TcM [TcId]
-- We expect the variables to all be bound, and all at
......
......@@ -46,10 +46,10 @@ import NameSet
import Bag
import ErrUtils ( ErrMsg, errDoc, pprLocErrMsg )
import BasicTypes
import ConLike ( ConLike(..), conLikeWrapId_maybe )
import ConLike ( ConLike(..))
import Util
import HscTypes (HscEnv, lookupTypeHscEnv, TypeEnv, lookupTypeEnv )
import NameEnv (lookupNameEnv)
import TcEnv (tcLookupIdMaybe)
import {-# SOURCE #-} TcSimplify ( tcSubsumes )
import FastString
import Outputable
import SrcLoc
......@@ -62,7 +62,7 @@ import FV ( fvVarList, unionFV )
import Control.Monad ( when )
import Data.Foldable ( toList )
import Data.List ( partition, mapAccumL, nub, sortBy, unfoldr )
import Data.List ( partition, mapAccumL, nub, sortBy, unfoldr, foldl')
import qualified Data.Set as Set
import Data.Semigroup ( Semigroup )
......@@ -1076,7 +1076,7 @@ mkHoleError ctxt ct@(CHoleCan { cc_hole = hole })
= givenConstraintsMsg ctxt
| otherwise = empty
; sub_msg <- validSubstitutions ct
; sub_msg <- validSubstitutions ctxt ct
; mkErrorMsgFromCt ctxt ct $
important hole_msg `mappend`
relevant_bindings (binds_msg $$ constraints_msg) `mappend`
......@@ -1128,26 +1128,37 @@ mkHoleError _ ct = pprPanic "mkHoleError" (ppr ct)
-- See Note [Valid substitutions include ...]
validSubstitutions :: Ct -> TcM SDoc
validSubstitutions ct | isExprHoleCt ct =
do { top_env <- getTopEnv
; rdr_env <- getGlobalRdrEnv
; gbl_env <- tcg_type_env <$> getGblEnv
; lcl_env <- getLclTypeEnv
validSubstitutions :: ReportErrCtxt -> Ct -> TcM SDoc
validSubstitutions (CEC {cec_encl = implics}) ct | isExprHoleCt ct =
do { rdr_env <- getGlobalRdrEnv
; dflags <- getDynFlags
; traceTc "findingValidSubstitutionsFor {" $ ppr wrapped_hole_ty
; (discards, substitutions) <-
go (gbl_env, lcl_env, top_env) (maxValidSubstitutions dflags)
$ localsFirst $ globalRdrEnvElts rdr_env
setTcLevel hole_lvl $
go (maxValidSubstitutions dflags) $
localsFirst $ globalRdrEnvElts rdr_env
; traceTc "}" empty
; return $ ppUnless (null substitutions) $
hang (text "Valid substitutions include")
2 (vcat (map (ppr_sub rdr_env) substitutions)
$$ ppWhen discards subsDiscardMsg) }
where
-- We extract the type of the hole from the constraint.
hole_ty :: TcPredType
hole_ty = ctEvPred (ctEvidence ct)
hole_loc = ctEvLoc $ ctEvidence ct
hole_env = ctLocEnv $ hole_loc
hole_lvl = ctLocLevel $ hole_loc
hole_env = ctLocEnv $ ctEvLoc $ ctEvidence ct
-- For checking, we wrap the type of the hole with all the givens
-- from all the implications in the context.
wrapped_hole_ty :: TcSigmaType
wrapped_hole_ty = foldl' wrapType hole_ty implics
-- We rearrange the elements to make locals appear at the top of the list,
-- since they're most likely to be relevant to the user
localsFirst :: [GlobalRdrElt] -> [GlobalRdrElt]
localsFirst elts = lcl ++ gbl
where (lcl, gbl) = partition gre_lcl elts
......@@ -1157,12 +1168,19 @@ validSubstitutions ct | isExprHoleCt ct =
is_id_bind (TcIdBndr_ExpType {}) = True
is_id_bind (TcTvBndr {}) = False
relBindSet = mkOccSet $ [ occName b | b <- tcl_bndrs hole_env
, is_id_bind b ]
-- The set of relevant bindings. We use it to make sure we don't repeat
-- ids from the relevant bindings again in the suggestions.
relBindSet :: OccSet
relBindSet = mkOccSet [ occName b | b <- tcl_bndrs hole_env
, is_id_bind b ]
-- We skip elements that are already in the "Relevant Bindings Include"
-- part of the error message, as given by the relBindSet.
shouldBeSkipped :: GlobalRdrElt -> Bool
shouldBeSkipped el = (occName $ gre_name el) `elemOccSet` relBindSet
-- For pretty printing, we look up the name and type of the substitution
-- we found.
ppr_sub :: GlobalRdrEnv -> Id -> SDoc
ppr_sub rdr_env id = case lookupGRE_Name rdr_env (idName id) of
Just elt -> sep [ idAndTy, nest 2 (parens $ pprNameProvenance elt)]
......@@ -1171,54 +1189,37 @@ validSubstitutions ct | isExprHoleCt ct =
ty = varType id
idAndTy = (pprPrefixOcc name <+> dcolon <+> pprType ty)
tyToId :: TyThing -> Maybe Id
tyToId (AnId i) = Just i
tyToId (AConLike c) = conLikeWrapId_maybe c
tyToId _ = Nothing
tcTyToId :: TcTyThing -> Maybe Id
tcTyToId (AGlobal id) = tyToId id
tcTyToId (ATcId id _) = Just id
tcTyToId _ = Nothing
substituteable :: Id -> Bool
substituteable = tcEqType hole_ty . varType
-- The real work happens here, where we invoke the typechecker to check
-- whether we the given type fits into the hole!
substituteable :: Id -> TcM Bool
substituteable id = wrapped_hole_ty `tcSubsumes` ty
where ty = varType id
lookupTopId :: HscEnv -> Name -> IO (Maybe Id)
lookupTopId env name =
maybe Nothing tyToId <$> lookupTypeHscEnv env name
lookupGblId :: TypeEnv -> Name -> Maybe Id
lookupGblId env name = maybe Nothing tyToId $ lookupTypeEnv env name
-- Kickoff the checking of the elements. The first argument
-- is a counter, so that we stop after finding functions up to the
-- limit the user gives us.
go :: Maybe Int -> [GlobalRdrElt] -> TcM (Bool, [Id])
go = go_ []
lookupLclId :: TcTypeEnv -> Name -> Maybe Id
lookupLclId env name = maybe Nothing tcTyToId $ lookupNameEnv env name
-- We iterate over the elements, checking each one in turn. If we've
-- already found -fmax-valid-substitutions=n elements, we look no further.
go_ :: [Id] -> Maybe Int -> [GlobalRdrElt] -> TcM (Bool, [Id])
go_ subs _ [] = return (False, reverse subs)
go_ subs (Just 0) _ = return (True, reverse subs)
go_ subs maxleft (el:elts) =
if shouldBeSkipped el then discard_it
else do { maybeId <- tcLookupIdMaybe (gre_name el)
; case maybeId of
Just id -> do { canSub <- substituteable id
; if canSub then (keep_it id) else discard_it }
_ -> discard_it
}
where discard_it = go_ subs maxleft elts
keep_it id = go_ (id:subs) ((\n -> n - 1) <$> maxleft) elts
go :: (TypeEnv, TcTypeEnv, HscEnv) -> Maybe Int -> [GlobalRdrElt]
-> TcM (Bool, [Id])
go = go_ []
go_ :: [Id] -> (TypeEnv, TcTypeEnv, HscEnv) -> Maybe Int -> [GlobalRdrElt]
-> TcM (Bool, [Id])
go_ subs _ _ [] = return (False, reverse subs)
go_ subs _ (Just 0) _ = return (True, reverse subs)
go_ subs envs@(gbl,lcl,top) maxleft (el:elts) =
if shouldBeSkipped el then discard_it
else do { maybeId <- liftIO lookupId
; case maybeId of
Just id | substituteable id ->
go_ (id:subs) envs ((\n -> n - 1) <$> maxleft) elts
_ -> discard_it }
where name = gre_name el
discard_it = go_ subs envs maxleft elts
getTopId = lookupTopId top name
gbl_id = lookupGblId gbl name
lcl_id = lookupLclId lcl name
lookupId = if (isJust lcl_id) then return lcl_id
else if (isJust gbl_id) then return gbl_id else getTopId
validSubstitutions _ = return empty
-- We don't (as of yet) handle holes in types, only in expressions.
validSubstitutions _ _ = return empty
-- See Note [Constraints include ...]
......@@ -1265,39 +1266,55 @@ Note [Valid substitutions include ...]
`validSubstitutions` returns the "Valid substitutions include ..." message.
For example, look at the following definitions in a file called test.hs:
ps :: String -> IO ()
ps = putStrLn
ps2 :: a -> IO ()
ps2 _ = putStrLn "hello, world"
main :: IO ()
main = _ "hello, world"
The hole in `main` would generate the message:
Valid substitutions include
ps :: String -> IO () ((defined at test.hs:2:1)
putStrLn :: String -> IO ()
(imported from ‘Prelude’ at test.hs:1:1
(and originally defined in ‘System.IO’))
putStr :: String -> IO ()
(imported from ‘Prelude’ at test.hs:1:1
(and originally defined in ‘System.IO’))
Valid substitutions are found by checking names in scope.
Currently the implementation only looks at exact type matches, as given by
`tcEqType`, so we DO NOT report `ps2` as a valid substitution in the example,
even though it fits in the hole. To determine that `ps2` fits in the hole,
we would need to check ids for subsumption, i.e. that the type of the hole is
a subtype of the id. This can be done using `tcSubType` from `TcUnify` and
`tcCheckSatisfiability` in `TcSimplify`. Unfortunately, `TcSimplify` uses
`TcErrors` to report errors found during constraint checking, so checking for
subsumption in holes would involve shuffling some code around in `TcSimplify`,
to make a non-error reporting constraint satisfiability checker which could
then be used for checking whether a given id satisfies the constraints imposed
by the hole.
import Data.List (inits)
f :: [String]
f = _ "hello, world"
The hole in `f` would generate the message:
Valid substitutions include
inits :: forall a. [a] -> [[a]]
(imported from ‘Data.List’ at tp.hs:3:19-23
(and originally defined in ‘base-4.10.0.0:Data.OldList’))
fail :: forall (m :: * -> *). Monad m => forall a. String -> m a
(imported from ‘Prelude’ at tp.hs:1:8-9
(and originally defined in ‘GHC.Base’))
mempty :: forall a. Monoid a => a
(imported from ‘Prelude’ at tp.hs:1:8-9
(and originally defined in ‘GHC.Base’))
pure :: forall (f :: * -> *). Applicative f => forall a. a -> f a
(imported from ‘Prelude’ at tp.hs:1:8-9
(and originally defined in ‘GHC.Base’))
return :: forall (m :: * -> *). Monad m => forall a. a -> m a
(imported from ‘Prelude’ at tp.hs:1:8-9
(and originally defined in ‘GHC.Base’))
read :: forall a. Read a => String -> a
(imported from ‘Prelude’ at tp.hs:1:8-9
(and originally defined in ‘Text.Read’))
lines :: String -> [String]
(imported from ‘Prelude’ at tp.hs:1:8-9
(and originally defined in ‘base-4.10.0.0:Data.OldList’))
words :: String -> [String]
(imported from ‘Prelude’ at tp.hs:1:8-9
(and originally defined in ‘base-4.10.0.0:Data.OldList’))
error :: forall (a :: TYPE r). GHC.Stack.Types.HasCallStack => [Char] -> a
(imported from ‘Prelude’ at tp.hs:1:8-9
(and originally defined in ‘GHC.Err’))
errorWithoutStackTrace :: forall (a :: TYPE r). [Char] -> a
(imported from ‘Prelude’ at tp.hs:1:8-9
(and originally defined in ‘GHC.Err’))
undefined :: forall (a :: TYPE r). GHC.Stack.Types.HasCallStack => a
(imported from ‘Prelude’ at tp.hs:1:8-9
(and originally defined in ‘GHC.Err’))
repeat :: forall a. a -> [a]
(imported from ‘Prelude’ at tp.hs:1:8-9
(and originally defined in ‘GHC.List’))
Valid substitutions are found by checking top level ids in scope, and checking
whether their type subsumes the type of the hole. We remove ids that are
local bindings, since they are already included in the relevant bindings
section of the hole error message.
Note [Constraints include ...]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......
......@@ -102,6 +102,7 @@ module TcRnTypes(
pprCtOrigin, pprCtLoc,
pushErrCtxt, pushErrCtxtSameOrigin,
SkolemInfo(..), pprSigSkolInfo, pprSkolInfo,
termEvidenceAllowed,
......@@ -110,6 +111,8 @@ module TcRnTypes(
isWanted, isGiven, isDerived, isGivenOrWDeriv,
ctEvRole,
wrapType,
-- Constraint solver plugins
TcPlugin(..), TcPluginResult(..), TcPluginSolver,
TcPluginM, runTcPluginM, unsafeTcPluginTcM,
......@@ -2484,6 +2487,18 @@ pprEvVarTheta ev_vars = pprTheta (map evVarPred ev_vars)
pprEvVarWithType :: EvVar -> SDoc
pprEvVarWithType v = ppr v <+> dcolon <+> pprType (evVarPred v)
-- | Wraps the given type with the constraints (via ic_given) in the given
-- implication, according to the variables mentioned (via ic_skols)
-- in the implication.
wrapType :: Type -> Implication -> Type
wrapType ty (Implic {ic_skols = skols, ic_given=givens}) =
wrapWithAllSkols $ mkFunTys (map idType givens) $ ty
where forAllTy :: Type -> TyVar -> Type
forAllTy ty tv = mkForAllTy tv Specified ty
wrapWithAllSkols ty = foldl forAllTy ty skols
{-
************************************************************************
* *
......
......@@ -9,6 +9,7 @@ module TcSimplify(
simplifyInteractive, solveEqualities,
simplifyWantedsTcM,
tcCheckSatisfiability,
tcSubsumes,
-- For Rules we need these
solveWanteds, solveWantedsAndDrop,
......@@ -44,6 +45,7 @@ import TrieMap () -- DV: for now
import Type
import TysWiredIn ( liftedRepTy )
import Unify ( tcMatchTyKi )
import TcUnify ( tcSubType_NC )
import Util
import Var
import VarSet
......@@ -481,6 +483,24 @@ simplifyDefault theta
; traceTc "reportUnsolved }" empty
; return () }
-- | Reports whether first type (ty_a) subsumes the second type (ty_b),
-- discarding any errors. Subsumption here means that the ty_b can fit into the
-- ty_a, i.e. `tcSubsumes a b == True` if b is a subtype of a.
-- N.B.: Make sure that the types contain all the constraints
-- contained in any associated implications.
tcSubsumes :: TcSigmaType -> TcSigmaType -> TcM Bool
tcSubsumes ty_a ty_b | ty_a `eqType` ty_b = return True
tcSubsumes ty_a ty_b = discardErrs $
do { (_, wanted, _) <- pushLevelAndCaptureConstraints $
tcSubType_NC ExprSigCtxt ty_b ty_a
; (rem, _) <- runTcS (simpl_top wanted)
-- We don't want any insoluble or simple constraints left,
-- but solved implications are ok (and neccessary for e.g. undefined)
; return (isEmptyBag (wc_simple rem)
&& isEmptyBag (wc_insol rem)
&& allBag (isSolvedStatus . ic_status) (wc_impl rem))
}
------------------
tcCheckSatisfiability :: Bag EvVar -> TcM Bool
-- Return True if satisfiable, False if definitely contradictory
......
module TcSimplify where
import GhcPrelude
import TcRnTypes ( TcM )
import TcType ( TcSigmaType )
-- This boot file exists solely to make tcSubsume avaialble in TcErrors
tcSubsumes :: TcSigmaType -> TcSigmaType -> TcM Bool
......@@ -4,3 +4,15 @@ T12468.hs:9:7: error:
• In the expression: _
In an equation for ‘f’: f I = _
• Relevant bindings include f :: T a -> a (bound at T12468.hs:9:1)
Valid substitutions include
maxBound :: forall a. Bounded a => a
(imported from ‘Prelude’ at T12468.hs:3:8-13
(and originally defined in ‘GHC.Enum’))
minBound :: forall a. Bounded a => a
(imported from ‘Prelude’ at T12468.hs:3:8-13
(and originally defined in ‘GHC.Enum’))
undefined :: forall (a :: TYPE r).
GHC.Stack.Types.HasCallStack =>
a
(imported from ‘Prelude’ at T12468.hs:3:8-13
(and originally defined in ‘GHC.Err’))
......@@ -12,3 +12,8 @@
In an equation for ‘it’: it = Just <$> _
• Relevant bindings include
it :: f (Maybe a) (bound at <interactive>:2:1)
Valid substitutions include
undefined :: forall (a :: TYPE r).
GHC.Stack.Types.HasCallStack =>
a
(imported from ‘Prelude’ (and originally defined in ‘GHC.Err’))
......@@ -6,3 +6,8 @@
• In the expression: _
In an equation for ‘it’: it = _
• Relevant bindings include it :: t (bound at <interactive>:1:1)
Valid substitutions include
undefined :: forall (a :: TYPE r).
GHC.Stack.Types.HasCallStack =>
a
(imported from ‘Prelude’ (and originally defined in ‘GHC.Err’))
......@@ -9,7 +9,19 @@ Defer03.hs:7:5: warning: [-Wtyped-holes (in -Wdefault)]
• In the expression: _
In an equation for ‘f’: f = _
• Relevant bindings include f :: Int (bound at Defer03.hs:7:1)
Valid substitutions include a :: Int (defined at Defer03.hs:4:1)
Valid substitutions include
a :: Int (defined at Defer03.hs:4:1)
undefined :: forall (a :: TYPE r).
GHC.Stack.Types.HasCallStack =>
a
(imported from ‘Prelude’ at Defer03.hs:1:8-11
(and originally defined in ‘GHC.Err’))
maxBound :: forall a. Bounded a => a
(imported from ‘Prelude’ at Defer03.hs:1:8-11
(and originally defined in ‘GHC.Enum’))
minBound :: forall a. Bounded a => a
(imported from ‘Prelude’ at Defer03.hs:1:8-11
(and originally defined in ‘GHC.Enum’))
Defer03.hs:4:5: error:
• Couldn't match expected type ‘Int’ with actual type ‘Char’
......@@ -21,7 +33,19 @@ Defer03.hs:7:5: error:
• In the expression: _
In an equation for ‘f’: f = _
• Relevant bindings include f :: Int (bound at Defer03.hs:7:1)
Valid substitutions include a :: Int (defined at Defer03.hs:4:1)
Valid substitutions include
a :: Int (defined at Defer03.hs:4:1)
undefined :: forall (a :: TYPE r).
GHC.Stack.Types.HasCallStack =>
a
(imported from ‘Prelude’ at Defer03.hs:1:8-11
(and originally defined in ‘GHC.Err’))
maxBound :: forall a. Bounded a => a
(imported from ‘Prelude’ at Defer03.hs:1:8-11
(and originally defined in ‘GHC.Enum’))
minBound :: forall a. Bounded a => a
(imported from ‘Prelude’ at Defer03.hs:1:8-11
(and originally defined in ‘GHC.Enum’))
Defer03.hs:4:5: warning: [-Wdeferred-type-errors (in -Wdefault)]
• Couldn't match expected type ‘Int’ with actual type ‘Char’
......@@ -33,7 +57,19 @@ Defer03.hs:7:5: warning: [-Wtyped-holes (in -Wdefault)]
• In the expression: _
In an equation for ‘f’: f = _
• Relevant bindings include f :: Int (bound at Defer03.hs:7:1)
Valid substitutions include a :: Int (defined at Defer03.hs:4:1)
Valid substitutions include
a :: Int (defined at Defer03.hs:4:1)
undefined :: forall (a :: TYPE r).
GHC.Stack.Types.HasCallStack =>
a
(imported from ‘Prelude’ at Defer03.hs:1:8-11
(and originally defined in ‘GHC.Err’))
maxBound :: forall a. Bounded a => a
(imported from ‘Prelude’ at Defer03.hs:1:8-11
(and originally defined in ‘GHC.Enum’))
minBound :: forall a. Bounded a => a
(imported from ‘Prelude’ at Defer03.hs:1:8-11
(and originally defined in ‘GHC.Enum’))
Defer03.hs:4:5: error:
• Couldn't match expected type ‘Int’ with actual type ‘Char’
......@@ -45,7 +81,19 @@ Defer03.hs:7:5: error:
• In the expression: _
In an equation for ‘f’: f = _
• Relevant bindings include f :: Int (bound at Defer03.hs:7:1)
Valid substitutions include a :: Int (defined at Defer03.hs:4:1)
Valid substitutions include
a :: Int (defined at Defer03.hs:4:1)
undefined :: forall (a :: TYPE r).
GHC.Stack.Types.HasCallStack =>
a
(imported from ‘Prelude’ at Defer03.hs:1:8-11
(and originally defined in ‘GHC.Err’))
maxBound :: forall a. Bounded a => a
(imported from ‘Prelude’ at Defer03.hs:1:8-11
(and originally defined in ‘GHC.Enum’))
minBound :: forall a. Bounded a => a
(imported from ‘Prelude’ at Defer03.hs:1:8-11
(and originally defined in ‘GHC.Enum’))
Defer03.hs:4:5: warning: [-Wdeferred-type-errors (in -Wdefault)]
• Couldn't match expected type ‘Int’ with actual type ‘Char’
......@@ -57,4 +105,16 @@ Defer03.hs:7:5: warning: [-Wtyped-holes (in -Wdefault)]
• In the expression: _
In an equation for ‘f’: f = _
• Relevant bindings include f :: Int (bound at Defer03.hs:7:1)
Valid substitutions include a :: Int (defined at Defer03.hs:4:1)
Valid substitutions include
a :: Int (defined at Defer03.hs:4:1)
undefined :: forall (a :: TYPE r).
GHC.Stack.Types.HasCallStack =>
a
(imported from ‘Prelude’ at Defer03.hs:1:8-11
(and originally defined in ‘GHC.Err’))
maxBound :: forall a. Bounded a => a
(imported from ‘Prelude’ at Defer03.hs:1:8-11
(and originally defined in ‘GHC.Enum’))
minBound :: forall a. Bounded a => a
(imported from ‘Prelude’ at Defer03.hs:1:8-11
(and originally defined in ‘GHC.Enum’))
......@@ -10,3 +10,9 @@ mod71.hs:4:9: error:
• Relevant bindings include
x :: t1 -> t -> t2 (bound at mod71.hs:4:3)
f :: (t1 -> t -> t2) -> t2 (bound at mod71.hs:4:1)
Valid substitutions include
undefined :: forall (a :: TYPE r).
GHC.Stack.Types.HasCallStack =>
a
(imported from ‘Prelude’ at mod71.hs:3:8
(and originally defined in ‘GHC.Err’))
......@@ -7,3 +7,9 @@ T12531.hs:6:11: warning: [-Wtyped-holes (in -Wdefault)]
• Relevant bindings include
x :: Int# (bound at T12531.hs:6:3)
f :: Int# -> Int (bound at T12531.hs:6:1)
Valid substitutions include
undefined :: forall (a :: TYPE r).
GHC.Stack.Types.HasCallStack =>
a
(imported from ‘Prelude’ at T12531.hs:3:8-13
(and originally defined in ‘GHC.Err’))
......@@ -10,6 +10,12 @@ T10267.hs:8:1: error:
• Relevant bindings include
x :: a (bound at T10267.hs:8:1)
j :: a -> a (bound at T10267.hs:8:1)
Valid substitutions include
undefined :: forall (a :: TYPE r).
GHC.Stack.Types.HasCallStack =>
a
(imported from ‘Prelude’ at T10267.hs:3:8-13
(and originally defined in ‘GHC.Err’))
T10267.hs:8:1: error:
• Found hole: _foo :: a -> a
......@@ -21,6 +27,18 @@ T10267.hs:8:1: error:
• In the expression: _foo
In an equation for ‘i’: i = _foo
• Relevant bindings include i :: a -> a (bound at T10267.hs:8:1)
Valid substitutions include
l :: forall a. a -> a (defined at T10267.hs:23:3)
k :: forall a. a -> a (defined at T10267.hs:14:3)
foo :: forall a. a -> a (defined at T10267.hs:33:1)
id :: forall a. a -> a
(imported from ‘Prelude’ at T10267.hs:3:8-13
(and originally defined in ‘GHC.Base’))
undefined :: forall (a :: TYPE r).
GHC.Stack.Types.HasCallStack =>
a
(imported from ‘Prelude’ at T10267.hs:3:8-13
(and originally defined in ‘GHC.Err’))
T10267.hs:14:3: error:
• Found hole: _foo :: a -> a
......@@ -32,6 +50,17 @@ T10267.hs:14:3: error:
• In the expression: _foo
In an equation for ‘k’: k = _foo
• Relevant bindings include k :: a -> a (bound at T10267.hs:14:3)
Valid substitutions include
l :: forall a. a -> a (defined at T10267.hs:23:3)
foo :: forall a. a -> a (defined at T10267.hs:33:1)
id :: forall a. a -> a
(imported from ‘Prelude’ at T10267.hs:3:8-13
(and originally defined in ‘GHC.Base’))
undefined :: forall (a :: TYPE r).
GHC.Stack.Types.HasCallStack =>
a
(imported from ‘Prelude’ at T10267.hs:3:8-13
(and originally defined in ‘GHC.Err’))
T10267.hs:23:3: error:
• Found hole: _ :: a
......@@ -44,3 +73,9 @@ T10267.hs:23:3: error:
• Relevant bindings include
x :: a (bound at T10267.hs:23:3)
l :: a -> a (bound at T10267.hs:23:3)
Valid substitutions include
undefined :: forall (a :: TYPE r).
GHC.Stack.Types.HasCallStack =>
a
(imported from ‘Prelude’ at T10267.hs:3:8-13
(and originally defined in ‘GHC.Err’))
......@@ -8,6 +8,60 @@ T13050.hs:4:9: warning: [-Wtyped-holes (in -Wdefault)]
y :: Int (bound at T13050.hs:4:5)
x :: Int (bound at T13050.hs:4:3)
f :: Int -> Int -> Int (bound at T13050.hs:4:1)
Valid substitutions include
(-) :: forall a. Num a => a -> a -> a
(imported from ‘Prelude’ at T13050.hs:1:8-17
(and originally defined in ‘GHC.Num’))
asTypeOf :: forall a. a -> a -> a
(imported from ‘Prelude’ at T13050.hs:1:8-17
(and originally defined in ‘GHC.Base’))
const :: forall a b. a -> b -> a
(imported from ‘Prelude’ at T13050.hs:1:8-17
(and originally defined in ‘GHC.Base’))
(*) :: forall a. Num a => a -> a -> a
(imported from ‘Prelude’ at T13050.hs:1:8-17
(and originally defined in ‘GHC.Num’))
(+) :: forall a. Num a => a -> a -> a
(imported from ‘Prelude’ at T13050.hs:1:8-17
(and originally defined in ‘GHC.Num’))
subtract :: forall a. Num a => a -> a -> a
(imported from ‘Prelude’ at T13050.hs:1:8-17
(and originally defined in ‘GHC.Num’))
(^) :: forall a b. (Num a, Integral b) => a -> b -> a
(imported from ‘Prelude’ at T13050.hs:1:8-17
(and originally defined in ‘GHC.Real’))
div :: forall a. Integral a => a -> a -> a
(imported from ‘Prelude’ at T13050.hs:1:8-17
(and originally defined in ‘GHC.Real’))
gcd :: forall a. Integral a => a -> a -> a
(imported from ‘Prelude’ at T13050.hs:1:8-17