{-# LANGUAGE CPP #-}
{-# LANGUAGE ViewPatterns, ScopedTypeVariables, DeriveFunctor, MultiWayIf #-}
module GHC.Core.Lint (
lintCoreBindings, lintUnfolding,
lintPassResult, lintInteractiveExpr, lintExpr,
lintAnnots, lintAxioms,
endPass, endPassIO,
dumpPassResult,
GHC.Core.Lint.dumpIfSet,
) where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Core
import GHC.Core.FVs
import GHC.Core.Utils
import GHC.Core.Stats ( coreBindsStats )
import GHC.Core.Opt.Monad
import GHC.Data.Bag
import GHC.Types.Literal
import GHC.Core.DataCon
import GHC.Builtin.Types.Prim
import GHC.Builtin.Types ( multiplicityTy )
import GHC.Tc.Utils.TcType ( isFloatingTy, isTyFamFree )
import GHC.Types.Var as Var
import GHC.Types.Var.Env
import GHC.Types.Var.Set
import GHC.Types.Unique.Set( nonDetEltsUniqSet )
import GHC.Types.Name
import GHC.Types.Name.Env
import GHC.Types.Id
import GHC.Types.Id.Info
import GHC.Core.Ppr
import GHC.Utils.Error
import GHC.Core.Coercion
import GHC.Types.SrcLoc
import GHC.Core.Type as Type
import GHC.Core.Multiplicity
import GHC.Core.UsageEnv
import GHC.Types.RepType
import GHC.Core.TyCo.Rep
import GHC.Core.TyCo.Subst
import GHC.Core.TyCo.FVs
import GHC.Core.TyCo.Ppr ( pprTyVar, pprTyVars )
import GHC.Core.TyCon as TyCon
import GHC.Core.Coercion.Axiom
import GHC.Core.Unify
import GHC.Types.Basic
import GHC.Utils.Error as Err
import GHC.Data.List.SetOps
import GHC.Builtin.Names
import GHC.Utils.Outputable as Outputable
import GHC.Data.FastString
import GHC.Utils.Misc
import GHC.Core.InstEnv ( instanceDFunId )
import GHC.Core.Coercion.Opt ( checkAxInstCo )
import GHC.Core.Opt.Arity ( typeArity )
import GHC.Types.Demand ( splitStrictSig, isDeadEndDiv )
import GHC.Driver.Types hiding (Usage)
import GHC.Driver.Session
import Control.Monad
import GHC.Utils.Monad
import Data.Foldable ( toList )
import Data.List.NonEmpty ( NonEmpty(..), groupWith )
import Data.List ( partition )
import Data.Maybe
import GHC.Data.Pair
import qualified GHC.LanguageExtensions as LangExt
endPass :: CoreToDo -> CoreProgram -> [CoreRule] -> CoreM ()
endPass :: CoreToDo -> CoreProgram -> [CoreRule] -> CoreM ()
endPass CoreToDo
pass CoreProgram
binds [CoreRule]
rules
= do { HscEnv
hsc_env <- CoreM HscEnv
getHscEnv
; PrintUnqualified
print_unqual <- CoreM PrintUnqualified
getPrintUnqualified
; IO () -> CoreM ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> CoreM ()) -> IO () -> CoreM ()
forall a b. (a -> b) -> a -> b
$ HscEnv
-> PrintUnqualified
-> CoreToDo
-> CoreProgram
-> [CoreRule]
-> IO ()
endPassIO HscEnv
hsc_env PrintUnqualified
print_unqual CoreToDo
pass CoreProgram
binds [CoreRule]
rules }
endPassIO :: HscEnv -> PrintUnqualified
-> CoreToDo -> CoreProgram -> [CoreRule] -> IO ()
endPassIO :: HscEnv
-> PrintUnqualified
-> CoreToDo
-> CoreProgram
-> [CoreRule]
-> IO ()
endPassIO HscEnv
hsc_env PrintUnqualified
print_unqual CoreToDo
pass CoreProgram
binds [CoreRule]
rules
= do { DynFlags
-> PrintUnqualified
-> Maybe DumpFlag
-> SDoc
-> SDoc
-> CoreProgram
-> [CoreRule]
-> IO ()
dumpPassResult DynFlags
dflags PrintUnqualified
print_unqual Maybe DumpFlag
mb_flag
(CoreToDo -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreToDo
pass) (CoreToDo -> SDoc
pprPassDetails CoreToDo
pass) CoreProgram
binds [CoreRule]
rules
; HscEnv -> CoreToDo -> CoreProgram -> IO ()
lintPassResult HscEnv
hsc_env CoreToDo
pass CoreProgram
binds }
where
dflags :: DynFlags
dflags = HscEnv -> DynFlags
hsc_dflags HscEnv
hsc_env
mb_flag :: Maybe DumpFlag
mb_flag = case CoreToDo -> Maybe DumpFlag
coreDumpFlag CoreToDo
pass of
Just DumpFlag
flag | DumpFlag -> DynFlags -> Bool
dopt DumpFlag
flag DynFlags
dflags -> DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
flag
| DumpFlag -> DynFlags -> Bool
dopt DumpFlag
Opt_D_verbose_core2core DynFlags
dflags -> DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
flag
Maybe DumpFlag
_ -> Maybe DumpFlag
forall a. Maybe a
Nothing
dumpIfSet :: DynFlags -> Bool -> CoreToDo -> SDoc -> SDoc -> IO ()
dumpIfSet :: DynFlags -> Bool -> CoreToDo -> SDoc -> SDoc -> IO ()
dumpIfSet DynFlags
dflags Bool
dump_me CoreToDo
pass SDoc
extra_info SDoc
doc
= DynFlags -> Bool -> String -> SDoc -> IO ()
Err.dumpIfSet DynFlags
dflags Bool
dump_me (DynFlags -> SDoc -> String
showSDoc DynFlags
dflags (CoreToDo -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreToDo
pass SDoc -> SDoc -> SDoc
<+> SDoc
extra_info)) SDoc
doc
dumpPassResult :: DynFlags
-> PrintUnqualified
-> Maybe DumpFlag
-> SDoc
-> SDoc
-> CoreProgram -> [CoreRule]
-> IO ()
dumpPassResult :: DynFlags
-> PrintUnqualified
-> Maybe DumpFlag
-> SDoc
-> SDoc
-> CoreProgram
-> [CoreRule]
-> IO ()
dumpPassResult DynFlags
dflags PrintUnqualified
unqual Maybe DumpFlag
mb_flag SDoc
hdr SDoc
extra_info CoreProgram
binds [CoreRule]
rules
= do { Maybe DumpFlag -> (DumpFlag -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe DumpFlag
mb_flag ((DumpFlag -> IO ()) -> IO ()) -> (DumpFlag -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \DumpFlag
flag -> do
let sty :: PprStyle
sty = PrintUnqualified -> PprStyle
mkDumpStyle PrintUnqualified
unqual
DumpAction
dumpAction DynFlags
dflags PprStyle
sty (DumpFlag -> DumpOptions
dumpOptionsFromFlag DumpFlag
flag)
(DynFlags -> SDoc -> String
showSDoc DynFlags
dflags SDoc
hdr) DumpFormat
FormatCore SDoc
dump_doc
; DynFlags -> JoinArity -> SDoc -> IO ()
Err.debugTraceMsg DynFlags
dflags JoinArity
2 SDoc
size_doc
}
where
size_doc :: SDoc
size_doc = [SDoc] -> SDoc
sep [String -> SDoc
text String
"Result size of" SDoc -> SDoc -> SDoc
<+> SDoc
hdr, JoinArity -> SDoc -> SDoc
nest JoinArity
2 (SDoc
equals SDoc -> SDoc -> SDoc
<+> CoreStats -> SDoc
forall a. Outputable a => a -> SDoc
ppr (CoreProgram -> CoreStats
coreBindsStats CoreProgram
binds))]
dump_doc :: SDoc
dump_doc = [SDoc] -> SDoc
vcat [ JoinArity -> SDoc -> SDoc
nest JoinArity
2 SDoc
extra_info
, SDoc
size_doc
, SDoc
blankLine
, CoreProgram -> SDoc
pprCoreBindingsWithSize CoreProgram
binds
, Bool -> SDoc -> SDoc
ppUnless ([CoreRule] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CoreRule]
rules) SDoc
pp_rules ]
pp_rules :: SDoc
pp_rules = [SDoc] -> SDoc
vcat [ SDoc
blankLine
, String -> SDoc
text String
"------ Local rules for imported ids --------"
, [CoreRule] -> SDoc
pprRules [CoreRule]
rules ]
coreDumpFlag :: CoreToDo -> Maybe DumpFlag
coreDumpFlag :: CoreToDo -> Maybe DumpFlag
coreDumpFlag (CoreDoSimplify {}) = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_verbose_core2core
coreDumpFlag (CoreDoPluginPass {}) = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_verbose_core2core
coreDumpFlag CoreToDo
CoreDoFloatInwards = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_verbose_core2core
coreDumpFlag (CoreDoFloatOutwards {}) = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_verbose_core2core
coreDumpFlag CoreToDo
CoreLiberateCase = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_verbose_core2core
coreDumpFlag CoreToDo
CoreDoStaticArgs = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_verbose_core2core
coreDumpFlag CoreToDo
CoreDoCallArity = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_dump_call_arity
coreDumpFlag CoreToDo
CoreDoExitify = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_dump_exitify
coreDumpFlag CoreToDo
CoreDoDemand = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_dump_stranal
coreDumpFlag CoreToDo
CoreDoCpr = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_dump_cpranal
coreDumpFlag CoreToDo
CoreDoWorkerWrapper = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_dump_worker_wrapper
coreDumpFlag CoreToDo
CoreDoSpecialising = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_dump_spec
coreDumpFlag CoreToDo
CoreDoSpecConstr = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_dump_spec
coreDumpFlag CoreToDo
CoreCSE = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_dump_cse
coreDumpFlag CoreToDo
CoreDesugar = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_dump_ds_preopt
coreDumpFlag CoreToDo
CoreDesugarOpt = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_dump_ds
coreDumpFlag CoreToDo
CoreTidy = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_dump_simpl
coreDumpFlag CoreToDo
CorePrep = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_dump_prep
coreDumpFlag CoreToDo
CoreOccurAnal = DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
Opt_D_dump_occur_anal
coreDumpFlag CoreToDo
CoreDoPrintCore = Maybe DumpFlag
forall a. Maybe a
Nothing
coreDumpFlag (CoreDoRuleCheck {}) = Maybe DumpFlag
forall a. Maybe a
Nothing
coreDumpFlag CoreToDo
CoreDoNothing = Maybe DumpFlag
forall a. Maybe a
Nothing
coreDumpFlag (CoreDoPasses {}) = Maybe DumpFlag
forall a. Maybe a
Nothing
lintPassResult :: HscEnv -> CoreToDo -> CoreProgram -> IO ()
lintPassResult :: HscEnv -> CoreToDo -> CoreProgram -> IO ()
lintPassResult HscEnv
hsc_env CoreToDo
pass CoreProgram
binds
| Bool -> Bool
not (GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_DoCoreLinting DynFlags
dflags)
= () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Bool
otherwise
= do { let (Bag SDoc
warns, Bag SDoc
errs) = DynFlags
-> CoreToDo -> [Var] -> CoreProgram -> (Bag SDoc, Bag SDoc)
lintCoreBindings DynFlags
dflags CoreToDo
pass (HscEnv -> [Var]
interactiveInScope HscEnv
hsc_env) CoreProgram
binds
; DynFlags -> String -> IO ()
Err.showPass DynFlags
dflags (String
"Core Linted result of " String -> String -> String
forall a. [a] -> [a] -> [a]
++ DynFlags -> CoreToDo -> String
forall a. Outputable a => DynFlags -> a -> String
showPpr DynFlags
dflags CoreToDo
pass)
; DynFlags
-> CoreToDo -> Bag SDoc -> Bag SDoc -> CoreProgram -> IO ()
displayLintResults DynFlags
dflags CoreToDo
pass Bag SDoc
warns Bag SDoc
errs CoreProgram
binds }
where
dflags :: DynFlags
dflags = HscEnv -> DynFlags
hsc_dflags HscEnv
hsc_env
displayLintResults :: DynFlags -> CoreToDo
-> Bag Err.MsgDoc -> Bag Err.MsgDoc -> CoreProgram
-> IO ()
displayLintResults :: DynFlags
-> CoreToDo -> Bag SDoc -> Bag SDoc -> CoreProgram -> IO ()
displayLintResults DynFlags
dflags CoreToDo
pass Bag SDoc
warns Bag SDoc
errs CoreProgram
binds
| Bool -> Bool
not (Bag SDoc -> Bool
forall a. Bag a -> Bool
isEmptyBag Bag SDoc
errs)
= do { DynFlags -> WarnReason -> Severity -> SrcSpan -> SDoc -> IO ()
putLogMsg DynFlags
dflags WarnReason
NoReason Severity
Err.SevDump SrcSpan
noSrcSpan
(SDoc -> IO ()) -> SDoc -> IO ()
forall a b. (a -> b) -> a -> b
$ PprStyle -> SDoc -> SDoc
withPprStyle PprStyle
defaultDumpStyle
([SDoc] -> SDoc
vcat [ String -> SDoc -> SDoc
lint_banner String
"errors" (CoreToDo -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreToDo
pass), Bag SDoc -> SDoc
Err.pprMessageBag Bag SDoc
errs
, String -> SDoc
text String
"*** Offending Program ***"
, CoreProgram -> SDoc
forall b. OutputableBndr b => [Bind b] -> SDoc
pprCoreBindings CoreProgram
binds
, String -> SDoc
text String
"*** End of Offense ***" ])
; DynFlags -> JoinArity -> IO ()
Err.ghcExit DynFlags
dflags JoinArity
1 }
| Bool -> Bool
not (Bag SDoc -> Bool
forall a. Bag a -> Bool
isEmptyBag Bag SDoc
warns)
, Bool -> Bool
not (DynFlags -> Bool
hasNoDebugOutput DynFlags
dflags)
, CoreToDo -> Bool
showLintWarnings CoreToDo
pass
= DynFlags -> WarnReason -> Severity -> SrcSpan -> SDoc -> IO ()
putLogMsg DynFlags
dflags WarnReason
NoReason Severity
Err.SevInfo SrcSpan
noSrcSpan
(SDoc -> IO ()) -> SDoc -> IO ()
forall a b. (a -> b) -> a -> b
$ PprStyle -> SDoc -> SDoc
withPprStyle PprStyle
defaultDumpStyle
(String -> SDoc -> SDoc
lint_banner String
"warnings" (CoreToDo -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreToDo
pass) SDoc -> SDoc -> SDoc
$$ Bag SDoc -> SDoc
Err.pprMessageBag ((SDoc -> SDoc) -> Bag SDoc -> Bag SDoc
forall a b. (a -> b) -> Bag a -> Bag b
mapBag (SDoc -> SDoc -> SDoc
$$ SDoc
blankLine) Bag SDoc
warns))
| Bool
otherwise = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
where
lint_banner :: String -> SDoc -> SDoc
lint_banner :: String -> SDoc -> SDoc
lint_banner String
string SDoc
pass = String -> SDoc
text String
"*** Core Lint" SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
string
SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
": in result of" SDoc -> SDoc -> SDoc
<+> SDoc
pass
SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"***"
showLintWarnings :: CoreToDo -> Bool
showLintWarnings :: CoreToDo -> Bool
showLintWarnings (CoreDoSimplify JoinArity
_ (SimplMode { sm_phase :: SimplMode -> CompilerPhase
sm_phase = CompilerPhase
InitialPhase })) = Bool
False
showLintWarnings CoreToDo
_ = Bool
True
lintInteractiveExpr :: String -> HscEnv -> CoreExpr -> IO ()
lintInteractiveExpr :: String -> HscEnv -> CoreExpr -> IO ()
lintInteractiveExpr String
what HscEnv
hsc_env CoreExpr
expr
| Bool -> Bool
not (GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_DoCoreLinting DynFlags
dflags)
= () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Just SDoc
err <- DynFlags -> [Var] -> CoreExpr -> Maybe SDoc
lintExpr DynFlags
dflags (HscEnv -> [Var]
interactiveInScope HscEnv
hsc_env) CoreExpr
expr
= do { SDoc -> IO ()
display_lint_err SDoc
err
; DynFlags -> JoinArity -> IO ()
Err.ghcExit DynFlags
dflags JoinArity
1 }
| Bool
otherwise
= () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
where
dflags :: DynFlags
dflags = HscEnv -> DynFlags
hsc_dflags HscEnv
hsc_env
display_lint_err :: SDoc -> IO ()
display_lint_err SDoc
err
= do { DynFlags -> WarnReason -> Severity -> SrcSpan -> SDoc -> IO ()
putLogMsg DynFlags
dflags WarnReason
NoReason Severity
Err.SevDump
SrcSpan
noSrcSpan
(SDoc -> IO ()) -> SDoc -> IO ()
forall a b. (a -> b) -> a -> b
$ PprStyle -> SDoc -> SDoc
withPprStyle PprStyle
defaultDumpStyle
([SDoc] -> SDoc
vcat [ String -> SDoc -> SDoc
lint_banner String
"errors" (String -> SDoc
text String
what)
, SDoc
err
, String -> SDoc
text String
"*** Offending Program ***"
, CoreExpr -> SDoc
forall b. OutputableBndr b => Expr b -> SDoc
pprCoreExpr CoreExpr
expr
, String -> SDoc
text String
"*** End of Offense ***" ])
; DynFlags -> JoinArity -> IO ()
Err.ghcExit DynFlags
dflags JoinArity
1 }
interactiveInScope :: HscEnv -> [Var]
interactiveInScope :: HscEnv -> [Var]
interactiveInScope HscEnv
hsc_env
= [Var]
tyvars [Var] -> [Var] -> [Var]
forall a. [a] -> [a] -> [a]
++ [Var]
ids
where
ictxt :: InteractiveContext
ictxt = HscEnv -> InteractiveContext
hsc_IC HscEnv
hsc_env
([ClsInst]
cls_insts, [FamInst]
_fam_insts) = InteractiveContext -> ([ClsInst], [FamInst])
ic_instances InteractiveContext
ictxt
te1 :: TypeEnv
te1 = [TyThing] -> TypeEnv
mkTypeEnvWithImplicits (InteractiveContext -> [TyThing]
ic_tythings InteractiveContext
ictxt)
te :: TypeEnv
te = TypeEnv -> [Var] -> TypeEnv
extendTypeEnvWithIds TypeEnv
te1 ((ClsInst -> Var) -> [ClsInst] -> [Var]
forall a b. (a -> b) -> [a] -> [b]
map ClsInst -> Var
instanceDFunId [ClsInst]
cls_insts)
ids :: [Var]
ids = TypeEnv -> [Var]
typeEnvIds TypeEnv
te
tyvars :: [Var]
tyvars = [LintedType] -> [Var]
tyCoVarsOfTypesList ([LintedType] -> [Var]) -> [LintedType] -> [Var]
forall a b. (a -> b) -> a -> b
$ (Var -> LintedType) -> [Var] -> [LintedType]
forall a b. (a -> b) -> [a] -> [b]
map Var -> LintedType
idType [Var]
ids
lintCoreBindings :: DynFlags -> CoreToDo -> [Var] -> CoreProgram -> (Bag MsgDoc, Bag MsgDoc)
lintCoreBindings :: DynFlags
-> CoreToDo -> [Var] -> CoreProgram -> (Bag SDoc, Bag SDoc)
lintCoreBindings DynFlags
dflags CoreToDo
pass [Var]
local_in_scope CoreProgram
binds
= DynFlags
-> LintFlags
-> [Var]
-> LintM ((), [UsageEnv])
-> (Bag SDoc, Bag SDoc)
forall a.
DynFlags -> LintFlags -> [Var] -> LintM a -> (Bag SDoc, Bag SDoc)
initL DynFlags
dflags LintFlags
flags [Var]
local_in_scope (LintM ((), [UsageEnv]) -> (Bag SDoc, Bag SDoc))
-> LintM ((), [UsageEnv]) -> (Bag SDoc, Bag SDoc)
forall a b. (a -> b) -> a -> b
$
LintLocInfo -> LintM ((), [UsageEnv]) -> LintM ((), [UsageEnv])
forall a. LintLocInfo -> LintM a -> LintM a
addLoc LintLocInfo
TopLevelBindings (LintM ((), [UsageEnv]) -> LintM ((), [UsageEnv]))
-> LintM ((), [UsageEnv]) -> LintM ((), [UsageEnv])
forall a b. (a -> b) -> a -> b
$
do { Bool -> SDoc -> LintM ()
checkL ([NonEmpty Var] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [NonEmpty Var]
dups) ([NonEmpty Var] -> SDoc
dupVars [NonEmpty Var]
dups)
; Bool -> SDoc -> LintM ()
checkL ([NonEmpty Name] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [NonEmpty Name]
ext_dups) ([NonEmpty Name] -> SDoc
dupExtVars [NonEmpty Name]
ext_dups)
; TopLevelFlag
-> [(Var, CoreExpr)]
-> ([Var] -> LintM ())
-> LintM ((), [UsageEnv])
forall a.
TopLevelFlag
-> [(Var, CoreExpr)] -> ([Var] -> LintM a) -> LintM (a, [UsageEnv])
lintRecBindings TopLevelFlag
TopLevel [(Var, CoreExpr)]
all_pairs (([Var] -> LintM ()) -> LintM ((), [UsageEnv]))
-> ([Var] -> LintM ()) -> LintM ((), [UsageEnv])
forall a b. (a -> b) -> a -> b
$ \[Var]
_ ->
() -> LintM ()
forall (m :: * -> *) a. Monad m => a -> m a
return () }
where
all_pairs :: [(Var, CoreExpr)]
all_pairs = CoreProgram -> [(Var, CoreExpr)]
forall b. [Bind b] -> [(b, Expr b)]
flattenBinds CoreProgram
binds
binders :: [Var]
binders = ((Var, CoreExpr) -> Var) -> [(Var, CoreExpr)] -> [Var]
forall a b. (a -> b) -> [a] -> [b]
map (Var, CoreExpr) -> Var
forall a b. (a, b) -> a
fst [(Var, CoreExpr)]
all_pairs
flags :: LintFlags
flags = (DynFlags -> LintFlags
defaultLintFlags DynFlags
dflags)
{ lf_check_global_ids :: Bool
lf_check_global_ids = Bool
check_globals
, lf_check_inline_loop_breakers :: Bool
lf_check_inline_loop_breakers = Bool
check_lbs
, lf_check_static_ptrs :: StaticPtrCheck
lf_check_static_ptrs = StaticPtrCheck
check_static_ptrs }
check_globals :: Bool
check_globals = case CoreToDo
pass of
CoreToDo
CoreTidy -> Bool
False
CoreToDo
CorePrep -> Bool
False
CoreToDo
_ -> Bool
True
check_lbs :: Bool
check_lbs = case CoreToDo
pass of
CoreToDo
CoreDesugar -> Bool
False
CoreToDo
CoreDesugarOpt -> Bool
False
CoreToDo
_ -> Bool
True
check_static_ptrs :: StaticPtrCheck
check_static_ptrs | Bool -> Bool
not (Extension -> DynFlags -> Bool
xopt Extension
LangExt.StaticPointers DynFlags
dflags) = StaticPtrCheck
AllowAnywhere
| Bool
otherwise = case CoreToDo
pass of
CoreDoFloatOutwards FloatOutSwitches
_ -> StaticPtrCheck
AllowAtTopLevel
CoreToDo
CoreTidy -> StaticPtrCheck
RejectEverywhere
CoreToDo
CorePrep -> StaticPtrCheck
AllowAtTopLevel
CoreToDo
_ -> StaticPtrCheck
AllowAnywhere
([Var]
_, [NonEmpty Var]
dups) = (Var -> Var -> Ordering) -> [Var] -> ([Var], [NonEmpty Var])
forall a. (a -> a -> Ordering) -> [a] -> ([a], [NonEmpty a])
removeDups Var -> Var -> Ordering
forall a. Ord a => a -> a -> Ordering
compare [Var]
binders
ext_dups :: [NonEmpty Name]
ext_dups = ([Name], [NonEmpty Name]) -> [NonEmpty Name]
forall a b. (a, b) -> b
snd ((Name -> Name -> Ordering) -> [Name] -> ([Name], [NonEmpty Name])
forall a. (a -> a -> Ordering) -> [a] -> ([a], [NonEmpty a])
removeDups Name -> Name -> Ordering
ord_ext ((Var -> Name) -> [Var] -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map Var -> Name
Var.varName [Var]
binders))
ord_ext :: Name -> Name -> Ordering
ord_ext Name
n1 Name
n2 | Just Module
m1 <- Name -> Maybe Module
nameModule_maybe Name
n1
, Just Module
m2 <- Name -> Maybe Module
nameModule_maybe Name
n2
= (Module, OccName) -> (Module, OccName) -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Module
m1, Name -> OccName
nameOccName Name
n1) (Module
m2, Name -> OccName
nameOccName Name
n2)
| Bool
otherwise = Ordering
LT
lintUnfolding :: Bool
-> DynFlags
-> SrcLoc
-> VarSet
-> CoreExpr
-> Maybe MsgDoc
lintUnfolding :: Bool -> DynFlags -> SrcLoc -> IdSet -> CoreExpr -> Maybe SDoc
lintUnfolding Bool
is_compulsory DynFlags
dflags SrcLoc
locn IdSet
var_set CoreExpr
expr
| Bag SDoc -> Bool
forall a. Bag a -> Bool
isEmptyBag Bag SDoc
errs = Maybe SDoc
forall a. Maybe a
Nothing
| Bool
otherwise = SDoc -> Maybe SDoc
forall a. a -> Maybe a
Just (Bag SDoc -> SDoc
pprMessageBag Bag SDoc
errs)
where
vars :: [Var]
vars = IdSet -> [Var]
forall elt. UniqSet elt -> [elt]
nonDetEltsUniqSet IdSet
var_set
(Bag SDoc
_warns, Bag SDoc
errs) = DynFlags
-> LintFlags
-> [Var]
-> LintM (LintedType, UsageEnv)
-> (Bag SDoc, Bag SDoc)
forall a.
DynFlags -> LintFlags -> [Var] -> LintM a -> (Bag SDoc, Bag SDoc)
initL DynFlags
dflags (DynFlags -> LintFlags
defaultLintFlags DynFlags
dflags) [Var]
vars (LintM (LintedType, UsageEnv) -> (Bag SDoc, Bag SDoc))
-> LintM (LintedType, UsageEnv) -> (Bag SDoc, Bag SDoc)
forall a b. (a -> b) -> a -> b
$
if Bool
is_compulsory
then LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintM a -> LintM a
noLPChecks LintM (LintedType, UsageEnv)
linter
else LintM (LintedType, UsageEnv)
linter
linter :: LintM (LintedType, UsageEnv)
linter = LintLocInfo
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintLocInfo -> LintM a -> LintM a
addLoc (SrcLoc -> LintLocInfo
ImportedUnfolding SrcLoc
locn) (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$
CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
expr
lintExpr :: DynFlags
-> [Var]
-> CoreExpr
-> Maybe MsgDoc
lintExpr :: DynFlags -> [Var] -> CoreExpr -> Maybe SDoc
lintExpr DynFlags
dflags [Var]
vars CoreExpr
expr
| Bag SDoc -> Bool
forall a. Bag a -> Bool
isEmptyBag Bag SDoc
errs = Maybe SDoc
forall a. Maybe a
Nothing
| Bool
otherwise = SDoc -> Maybe SDoc
forall a. a -> Maybe a
Just (Bag SDoc -> SDoc
pprMessageBag Bag SDoc
errs)
where
(Bag SDoc
_warns, Bag SDoc
errs) = DynFlags
-> LintFlags
-> [Var]
-> LintM (LintedType, UsageEnv)
-> (Bag SDoc, Bag SDoc)
forall a.
DynFlags -> LintFlags -> [Var] -> LintM a -> (Bag SDoc, Bag SDoc)
initL DynFlags
dflags (DynFlags -> LintFlags
defaultLintFlags DynFlags
dflags) [Var]
vars LintM (LintedType, UsageEnv)
linter
linter :: LintM (LintedType, UsageEnv)
linter = LintLocInfo
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintLocInfo -> LintM a -> LintM a
addLoc LintLocInfo
TopLevelBindings (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$
CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
expr
lintRecBindings :: TopLevelFlag -> [(Id, CoreExpr)]
-> ([LintedId] -> LintM a) -> LintM (a, [UsageEnv])
lintRecBindings :: forall a.
TopLevelFlag
-> [(Var, CoreExpr)] -> ([Var] -> LintM a) -> LintM (a, [UsageEnv])
lintRecBindings TopLevelFlag
top_lvl [(Var, CoreExpr)]
pairs [Var] -> LintM a
thing_inside
= TopLevelFlag
-> [Var]
-> ([Var] -> LintM (a, [UsageEnv]))
-> LintM (a, [UsageEnv])
forall a. TopLevelFlag -> [Var] -> ([Var] -> LintM a) -> LintM a
lintIdBndrs TopLevelFlag
top_lvl [Var]
bndrs (([Var] -> LintM (a, [UsageEnv])) -> LintM (a, [UsageEnv]))
-> ([Var] -> LintM (a, [UsageEnv])) -> LintM (a, [UsageEnv])
forall a b. (a -> b) -> a -> b
$ \ [Var]
bndrs' ->
do { [UsageEnv]
ues <- (Var -> CoreExpr -> LintM UsageEnv)
-> [Var] -> [CoreExpr] -> LintM [UsageEnv]
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM Var -> CoreExpr -> LintM UsageEnv
lint_pair [Var]
bndrs' [CoreExpr]
rhss
; a
a <- [Var] -> LintM a
thing_inside [Var]
bndrs'
; (a, [UsageEnv]) -> LintM (a, [UsageEnv])
forall (m :: * -> *) a. Monad m => a -> m a
return (a
a, [UsageEnv]
ues) }
where
([Var]
bndrs, [CoreExpr]
rhss) = [(Var, CoreExpr)] -> ([Var], [CoreExpr])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Var, CoreExpr)]
pairs
lint_pair :: Var -> CoreExpr -> LintM UsageEnv
lint_pair Var
bndr' CoreExpr
rhs
= LintLocInfo -> LintM UsageEnv -> LintM UsageEnv
forall a. LintLocInfo -> LintM a -> LintM a
addLoc (Var -> LintLocInfo
RhsOf Var
bndr') (LintM UsageEnv -> LintM UsageEnv)
-> LintM UsageEnv -> LintM UsageEnv
forall a b. (a -> b) -> a -> b
$
do { (LintedType
rhs_ty, UsageEnv
ue) <- Var -> CoreExpr -> LintM (LintedType, UsageEnv)
lintRhs Var
bndr' CoreExpr
rhs
; TopLevelFlag
-> RecFlag -> Var -> CoreExpr -> LintedType -> LintM ()
lintLetBind TopLevelFlag
top_lvl RecFlag
Recursive Var
bndr' CoreExpr
rhs LintedType
rhs_ty
; UsageEnv -> LintM UsageEnv
forall (m :: * -> *) a. Monad m => a -> m a
return UsageEnv
ue }
lintLetBody :: [LintedId] -> CoreExpr -> LintM (LintedType, UsageEnv)
lintLetBody :: [Var] -> CoreExpr -> LintM (LintedType, UsageEnv)
lintLetBody [Var]
bndrs CoreExpr
body
= do { (LintedType
body_ty, UsageEnv
body_ue) <- LintLocInfo
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintLocInfo -> LintM a -> LintM a
addLoc ([Var] -> LintLocInfo
BodyOfLetRec [Var]
bndrs) (CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
body)
; (Var -> LintM ()) -> [Var] -> LintM ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (LintedType -> Var -> LintM ()
lintJoinBndrType LintedType
body_ty) [Var]
bndrs
; (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (LintedType
body_ty, UsageEnv
body_ue) }
lintLetBind :: TopLevelFlag -> RecFlag -> LintedId
-> CoreExpr -> LintedType -> LintM ()
lintLetBind :: TopLevelFlag
-> RecFlag -> Var -> CoreExpr -> LintedType -> LintM ()
lintLetBind TopLevelFlag
top_lvl RecFlag
rec_flag Var
binder CoreExpr
rhs LintedType
rhs_ty
= do { let binder_ty :: LintedType
binder_ty = Var -> LintedType
idType Var
binder
; LintedType -> LintedType -> SDoc -> LintM ()
ensureEqTys LintedType
binder_ty LintedType
rhs_ty (Var -> SDoc -> LintedType -> SDoc
mkRhsMsg Var
binder (String -> SDoc
text String
"RHS") LintedType
rhs_ty)
; Bool -> SDoc -> LintM ()
checkL (Bool -> Bool
not (Var -> Bool
isCoVar Var
binder) Bool -> Bool -> Bool
|| CoreExpr -> Bool
forall b. Expr b -> Bool
isCoArg CoreExpr
rhs)
(Var -> CoreExpr -> SDoc
mkLetErr Var
binder CoreExpr
rhs)
; Bool -> SDoc -> LintM ()
checkL ( Var -> Bool
isJoinId Var
binder
Bool -> Bool -> Bool
|| Bool -> Bool
not (HasDebugCallStack => LintedType -> Bool
LintedType -> Bool
isUnliftedType LintedType
binder_ty)
Bool -> Bool -> Bool
|| (RecFlag -> Bool
isNonRec RecFlag
rec_flag Bool -> Bool -> Bool
&& CoreExpr -> Bool
exprOkForSpeculation CoreExpr
rhs)
Bool -> Bool -> Bool
|| CoreExpr -> Bool
exprIsTickedString CoreExpr
rhs)
(Var -> SDoc -> SDoc
badBndrTyMsg Var
binder (String -> SDoc
text String
"unlifted"))
; Bool -> SDoc -> LintM ()
checkL (Bool -> Bool
not (Var -> Bool
isStrictId Var
binder)
Bool -> Bool -> Bool
|| (RecFlag -> Bool
isNonRec RecFlag
rec_flag Bool -> Bool -> Bool
&& Bool -> Bool
not (TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl))
Bool -> Bool -> Bool
|| CoreExpr -> Bool
exprIsTickedString CoreExpr
rhs)
(Var -> SDoc
mkStrictMsg Var
binder)
; Bool -> SDoc -> LintM ()
checkL (Bool -> Bool
not (TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl Bool -> Bool -> Bool
&& LintedType
binder_ty LintedType -> LintedType -> Bool
`eqType` LintedType
addrPrimTy)
Bool -> Bool -> Bool
|| CoreExpr -> Bool
exprIsTickedString CoreExpr
rhs)
(Var -> SDoc
mkTopNonLitStrMsg Var
binder)
; LintFlags
flags <- LintM LintFlags
getLintFlags
; case Var -> Maybe JoinArity
isJoinId_maybe Var
binder of
Maybe JoinArity
Nothing -> () -> LintM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just JoinArity
arity -> Bool -> SDoc -> LintM ()
checkL (JoinArity -> LintedType -> Bool
isValidJoinPointType JoinArity
arity LintedType
binder_ty)
(Var -> LintedType -> SDoc
mkInvalidJoinPointMsg Var
binder LintedType
binder_ty)
; Bool -> LintM () -> LintM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (LintFlags -> Bool
lf_check_inline_loop_breakers LintFlags
flags
Bool -> Bool -> Bool
&& Unfolding -> Bool
isStableUnfolding (Var -> Unfolding
realIdUnfolding Var
binder)
Bool -> Bool -> Bool
&& OccInfo -> Bool
isStrongLoopBreaker (Var -> OccInfo
idOccInfo Var
binder)
Bool -> Bool -> Bool
&& InlinePragma -> Bool
isInlinePragma (Var -> InlinePragma
idInlinePragma Var
binder))
(SDoc -> LintM ()
addWarnL (String -> SDoc
text String
"INLINE binder is (non-rule) loop breaker:" SDoc -> SDoc -> SDoc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
binder))
; Bool -> SDoc -> LintM ()
checkL (LintedType -> [OneShotInfo]
typeArity (Var -> LintedType
idType Var
binder) [OneShotInfo] -> JoinArity -> Bool
forall a. [a] -> JoinArity -> Bool
`lengthAtLeast` Var -> JoinArity
idArity Var
binder)
(String -> SDoc
text String
"idArity" SDoc -> SDoc -> SDoc
<+> JoinArity -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Var -> JoinArity
idArity Var
binder) SDoc -> SDoc -> SDoc
<+>
String -> SDoc
text String
"exceeds typeArity" SDoc -> SDoc -> SDoc
<+>
JoinArity -> SDoc
forall a. Outputable a => a -> SDoc
ppr ([OneShotInfo] -> JoinArity
forall (t :: * -> *) a. Foldable t => t a -> JoinArity
length (LintedType -> [OneShotInfo]
typeArity (Var -> LintedType
idType Var
binder))) SDoc -> SDoc -> SDoc
<> SDoc
colon SDoc -> SDoc -> SDoc
<+>
Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
binder)
; case StrictSig -> ([Demand], Divergence)
splitStrictSig (Var -> StrictSig
idStrictness Var
binder) of
([Demand]
demands, Divergence
result_info) | Divergence -> Bool
isDeadEndDiv Divergence
result_info ->
Bool -> SDoc -> LintM ()
checkL ([Demand]
demands [Demand] -> JoinArity -> Bool
forall a. [a] -> JoinArity -> Bool
`lengthAtLeast` Var -> JoinArity
idArity Var
binder)
(String -> SDoc
text String
"idArity" SDoc -> SDoc -> SDoc
<+> JoinArity -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Var -> JoinArity
idArity Var
binder) SDoc -> SDoc -> SDoc
<+>
String -> SDoc
text String
"exceeds arity imposed by the strictness signature" SDoc -> SDoc -> SDoc
<+>
StrictSig -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Var -> StrictSig
idStrictness Var
binder) SDoc -> SDoc -> SDoc
<> SDoc
colon SDoc -> SDoc -> SDoc
<+>
Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
binder)
([Demand], Divergence)
_ -> () -> LintM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
; LintLocInfo -> LintM () -> LintM ()
forall a. LintLocInfo -> LintM a -> LintM a
addLoc (Var -> LintLocInfo
RuleOf Var
binder) (LintM () -> LintM ()) -> LintM () -> LintM ()
forall a b. (a -> b) -> a -> b
$ (CoreRule -> LintM ()) -> [CoreRule] -> LintM ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Var -> LintedType -> CoreRule -> LintM ()
lintCoreRule Var
binder LintedType
binder_ty) (Var -> [CoreRule]
idCoreRules Var
binder)
; LintLocInfo -> LintM () -> LintM ()
forall a. LintLocInfo -> LintM a -> LintM a
addLoc (Var -> LintLocInfo
UnfoldingOf Var
binder) (LintM () -> LintM ()) -> LintM () -> LintM ()
forall a b. (a -> b) -> a -> b
$
Var -> LintedType -> Unfolding -> LintM ()
lintIdUnfolding Var
binder LintedType
binder_ty (Var -> Unfolding
idUnfolding Var
binder)
; () -> LintM ()
forall (m :: * -> *) a. Monad m => a -> m a
return () }
lintRhs :: Id -> CoreExpr -> LintM (LintedType, UsageEnv)
lintRhs :: Var -> CoreExpr -> LintM (LintedType, UsageEnv)
lintRhs Var
bndr CoreExpr
rhs
| Just JoinArity
arity <- Var -> Maybe JoinArity
isJoinId_maybe Var
bndr
= JoinArity -> Maybe Var -> CoreExpr -> LintM (LintedType, UsageEnv)
lintJoinLams JoinArity
arity (Var -> Maybe Var
forall a. a -> Maybe a
Just Var
bndr) CoreExpr
rhs
| AlwaysTailCalled JoinArity
arity <- OccInfo -> TailCallInfo
tailCallInfo (Var -> OccInfo
idOccInfo Var
bndr)
= JoinArity -> Maybe Var -> CoreExpr -> LintM (LintedType, UsageEnv)
lintJoinLams JoinArity
arity Maybe Var
forall a. Maybe a
Nothing CoreExpr
rhs
lintRhs Var
_bndr CoreExpr
rhs = (LintFlags -> StaticPtrCheck)
-> LintM LintFlags -> LintM StaticPtrCheck
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap LintFlags -> StaticPtrCheck
lf_check_static_ptrs LintM LintFlags
getLintFlags LintM StaticPtrCheck
-> (StaticPtrCheck -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= StaticPtrCheck -> LintM (LintedType, UsageEnv)
go
where
go :: StaticPtrCheck -> LintM (OutType, UsageEnv)
go :: StaticPtrCheck -> LintM (LintedType, UsageEnv)
go StaticPtrCheck
AllowAtTopLevel
| ([Var]
binders0, CoreExpr
rhs') <- CoreExpr -> ([Var], CoreExpr)
collectTyBinders CoreExpr
rhs
, Just (CoreExpr
fun, LintedType
t, CoreExpr
info, CoreExpr
e) <- CoreExpr -> Maybe (CoreExpr, LintedType, CoreExpr, CoreExpr)
collectMakeStaticArgs CoreExpr
rhs'
= LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintM a -> LintM a
markAllJoinsBad (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$
(Var
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv)
-> [Var]
-> LintM (LintedType, UsageEnv)
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr
Var -> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
lintLambda
(do (LintedType, UsageEnv)
fun_ty_ue <- CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
fun
(LintedType, UsageEnv)
-> [CoreExpr] -> LintM (LintedType, UsageEnv)
lintCoreArgs (LintedType, UsageEnv)
fun_ty_ue [LintedType -> CoreExpr
forall b. LintedType -> Expr b
Type LintedType
t, CoreExpr
info, CoreExpr
e]
)
[Var]
binders0
go StaticPtrCheck
_ = LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintM a -> LintM a
markAllJoinsBad (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$ CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
rhs
lintJoinLams :: JoinArity -> Maybe Id -> CoreExpr -> LintM (LintedType, UsageEnv)
lintJoinLams :: JoinArity -> Maybe Var -> CoreExpr -> LintM (LintedType, UsageEnv)
lintJoinLams JoinArity
join_arity Maybe Var
enforce CoreExpr
rhs
= JoinArity -> CoreExpr -> LintM (LintedType, UsageEnv)
go JoinArity
join_arity CoreExpr
rhs
where
go :: JoinArity -> CoreExpr -> LintM (LintedType, UsageEnv)
go JoinArity
0 CoreExpr
expr = CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
expr
go JoinArity
n (Lam Var
var CoreExpr
body) = Var -> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
lintLambda Var
var (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$ JoinArity -> CoreExpr -> LintM (LintedType, UsageEnv)
go (JoinArity
nJoinArity -> JoinArity -> JoinArity
forall a. Num a => a -> a -> a
-JoinArity
1) CoreExpr
body
go JoinArity
n CoreExpr
expr | Just Var
bndr <- Maybe Var
enforce
= SDoc -> LintM (LintedType, UsageEnv)
forall a. SDoc -> LintM a
failWithL (SDoc -> LintM (LintedType, UsageEnv))
-> SDoc -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$ Var -> JoinArity -> JoinArity -> CoreExpr -> SDoc
mkBadJoinArityMsg Var
bndr JoinArity
join_arity JoinArity
n CoreExpr
rhs
| Bool
otherwise
= LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintM a -> LintM a
markAllJoinsBad (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$ CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
expr
lintIdUnfolding :: Id -> Type -> Unfolding -> LintM ()
lintIdUnfolding :: Var -> LintedType -> Unfolding -> LintM ()
lintIdUnfolding Var
bndr LintedType
bndr_ty Unfolding
uf
| Unfolding -> Bool
isStableUnfolding Unfolding
uf
, Just CoreExpr
rhs <- Unfolding -> Maybe CoreExpr
maybeUnfoldingTemplate Unfolding
uf
= do { LintedType
ty <- (LintedType, UsageEnv) -> LintedType
forall a b. (a, b) -> a
fst ((LintedType, UsageEnv) -> LintedType)
-> LintM (LintedType, UsageEnv) -> LintM LintedType
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (if Unfolding -> Bool
isCompulsoryUnfolding Unfolding
uf
then LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintM a -> LintM a
noLPChecks (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$ Var -> CoreExpr -> LintM (LintedType, UsageEnv)
lintRhs Var
bndr CoreExpr
rhs
else Var -> CoreExpr -> LintM (LintedType, UsageEnv)
lintRhs Var
bndr CoreExpr
rhs)
; LintedType -> LintedType -> SDoc -> LintM ()
ensureEqTys LintedType
bndr_ty LintedType
ty (Var -> SDoc -> LintedType -> SDoc
mkRhsMsg Var
bndr (String -> SDoc
text String
"unfolding") LintedType
ty) }
lintIdUnfolding Var
_ LintedType
_ Unfolding
_
= () -> LintM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
type LintedType = Type
type LintedKind = Kind
type LintedCoercion = Coercion
type LintedTyCoVar = TyCoVar
type LintedId = Id
lintCastExpr :: CoreExpr -> LintedType -> Coercion -> LintM LintedType
lintCastExpr :: CoreExpr -> LintedType -> Coercion -> LintM LintedType
lintCastExpr CoreExpr
expr LintedType
expr_ty Coercion
co
= do { Coercion
co' <- Coercion -> LintM Coercion
lintCoercion Coercion
co
; let (Pair LintedType
from_ty LintedType
to_ty, Role
role) = Coercion -> (Pair LintedType, Role)
coercionKindRole Coercion
co'
; LintedType -> SDoc -> LintM ()
checkValueType LintedType
to_ty (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
String -> SDoc
text String
"target of cast" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
quotes (Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co')
; Coercion -> Role -> Role -> LintM ()
forall thing. Outputable thing => thing -> Role -> Role -> LintM ()
lintRole Coercion
co' Role
Representational Role
role
; LintedType -> LintedType -> SDoc -> LintM ()
ensureEqTys LintedType
from_ty LintedType
expr_ty (CoreExpr -> Coercion -> LintedType -> LintedType -> SDoc
mkCastErr CoreExpr
expr Coercion
co' LintedType
from_ty LintedType
expr_ty)
; LintedType -> LintM LintedType
forall (m :: * -> *) a. Monad m => a -> m a
return LintedType
to_ty }
lintCoreExpr :: CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr :: CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr (Var Var
var)
= Var -> JoinArity -> LintM (LintedType, UsageEnv)
lintIdOcc Var
var JoinArity
0
lintCoreExpr (Lit Literal
lit)
= (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (Literal -> LintedType
literalType Literal
lit, UsageEnv
zeroUE)
lintCoreExpr (Cast CoreExpr
expr Coercion
co)
= do (LintedType
expr_ty, UsageEnv
ue) <- LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintM a -> LintM a
markAllJoinsBad (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$ CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
expr
LintedType
to_ty <- CoreExpr -> LintedType -> Coercion -> LintM LintedType
lintCastExpr CoreExpr
expr LintedType
expr_ty Coercion
co
(LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (LintedType
to_ty, UsageEnv
ue)
lintCoreExpr (Tick Tickish Var
tickish CoreExpr
expr)
= do case Tickish Var
tickish of
Breakpoint JoinArity
_ [Var]
ids -> [Var] -> (Var -> LintM (Var, LintedType)) -> LintM ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Var]
ids ((Var -> LintM (Var, LintedType)) -> LintM ())
-> (Var -> LintM (Var, LintedType)) -> LintM ()
forall a b. (a -> b) -> a -> b
$ \Var
id -> do
Var -> LintM ()
checkDeadIdOcc Var
id
Var -> LintM (Var, LintedType)
lookupIdInScope Var
id
Tickish Var
_ -> () -> LintM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Bool
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. Bool -> LintM a -> LintM a
markAllJoinsBadIf Bool
block_joins (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$ CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
expr
where
block_joins :: Bool
block_joins = Bool -> Bool
not (Tickish Var
tickish Tickish Var -> TickishScoping -> Bool
forall id. Tickish id -> TickishScoping -> Bool
`tickishScopesLike` TickishScoping
SoftScope)
lintCoreExpr (Let (NonRec Var
tv (Type LintedType
ty)) CoreExpr
body)
| Var -> Bool
isTyVar Var
tv
=
do { LintedType
ty' <- LintedType -> LintM LintedType
lintType LintedType
ty
; Var
-> (Var -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv)
forall a. Var -> (Var -> LintM a) -> LintM a
lintTyBndr Var
tv ((Var -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv))
-> (Var -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$ \ Var
tv' ->
do { LintLocInfo -> LintM () -> LintM ()
forall a. LintLocInfo -> LintM a -> LintM a
addLoc (Var -> LintLocInfo
RhsOf Var
tv) (LintM () -> LintM ()) -> LintM () -> LintM ()
forall a b. (a -> b) -> a -> b
$ Var -> LintedType -> LintM ()
lintTyKind Var
tv' LintedType
ty'
; Var
-> LintedType
-> LintM (LintedType, UsageEnv)
-> LintM (LintedType, UsageEnv)
forall a. Var -> LintedType -> LintM a -> LintM a
extendTvSubstL Var
tv LintedType
ty' (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$
LintLocInfo
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintLocInfo -> LintM a -> LintM a
addLoc ([Var] -> LintLocInfo
BodyOfLetRec [Var
tv]) (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$
CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
body } }
lintCoreExpr (Let (NonRec Var
bndr CoreExpr
rhs) CoreExpr
body)
| Var -> Bool
isId Var
bndr
= do {
(LintedType
rhs_ty, UsageEnv
let_ue) <- Var -> CoreExpr -> LintM (LintedType, UsageEnv)
lintRhs Var
bndr CoreExpr
rhs
; BindingSite
-> Var
-> (Var -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv)
forall a. BindingSite -> Var -> (Var -> LintM a) -> LintM a
lintBinder BindingSite
LetBind Var
bndr ((Var -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv))
-> (Var -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$ \Var
bndr' ->
do { TopLevelFlag
-> RecFlag -> Var -> CoreExpr -> LintedType -> LintM ()
lintLetBind TopLevelFlag
NotTopLevel RecFlag
NonRecursive Var
bndr' CoreExpr
rhs LintedType
rhs_ty
; Var
-> UsageEnv
-> LintM (LintedType, UsageEnv)
-> LintM (LintedType, UsageEnv)
forall a. Var -> UsageEnv -> LintM a -> LintM a
addAliasUE Var
bndr UsageEnv
let_ue ([Var] -> CoreExpr -> LintM (LintedType, UsageEnv)
lintLetBody [Var
bndr'] CoreExpr
body) } }
| Bool
otherwise
= SDoc -> LintM (LintedType, UsageEnv)
forall a. SDoc -> LintM a
failWithL (Var -> CoreExpr -> SDoc
mkLetErr Var
bndr CoreExpr
rhs)
lintCoreExpr e :: CoreExpr
e@(Let (Rec [(Var, CoreExpr)]
pairs) CoreExpr
body)
= do {
Bool -> SDoc -> LintM ()
checkL (Bool -> Bool
not ([(Var, CoreExpr)] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Var, CoreExpr)]
pairs)) (CoreExpr -> SDoc
emptyRec CoreExpr
e)
; let ([Var]
_, [NonEmpty Var]
dups) = (Var -> Var -> Ordering) -> [Var] -> ([Var], [NonEmpty Var])
forall a. (a -> a -> Ordering) -> [a] -> ([a], [NonEmpty a])
removeDups Var -> Var -> Ordering
forall a. Ord a => a -> a -> Ordering
compare [Var]
bndrs
; Bool -> SDoc -> LintM ()
checkL ([NonEmpty Var] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [NonEmpty Var]
dups) ([NonEmpty Var] -> SDoc
dupVars [NonEmpty Var]
dups)
; Bool -> SDoc -> LintM ()
checkL ((Var -> Bool) -> [Var] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Var -> Bool
isJoinId [Var]
bndrs Bool -> Bool -> Bool
|| (Var -> Bool) -> [Var] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Bool -> Bool
not (Bool -> Bool) -> (Var -> Bool) -> Var -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Var -> Bool
isJoinId) [Var]
bndrs) (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
[Var] -> SDoc
mkInconsistentRecMsg [Var]
bndrs
; ((LintedType
body_type, UsageEnv
body_ue), [UsageEnv]
ues) <-
TopLevelFlag
-> [(Var, CoreExpr)]
-> ([Var] -> LintM (LintedType, UsageEnv))
-> LintM ((LintedType, UsageEnv), [UsageEnv])
forall a.
TopLevelFlag
-> [(Var, CoreExpr)] -> ([Var] -> LintM a) -> LintM (a, [UsageEnv])
lintRecBindings TopLevelFlag
NotTopLevel [(Var, CoreExpr)]
pairs (([Var] -> LintM (LintedType, UsageEnv))
-> LintM ((LintedType, UsageEnv), [UsageEnv]))
-> ([Var] -> LintM (LintedType, UsageEnv))
-> LintM ((LintedType, UsageEnv), [UsageEnv])
forall a b. (a -> b) -> a -> b
$ \ [Var]
bndrs' ->
[Var] -> CoreExpr -> LintM (LintedType, UsageEnv)
lintLetBody [Var]
bndrs' CoreExpr
body
; (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (LintedType
body_type, UsageEnv
body_ue UsageEnv -> UsageEnv -> UsageEnv
`addUE` LintedType -> UsageEnv -> UsageEnv
scaleUE LintedType
Many ((UsageEnv -> UsageEnv -> UsageEnv) -> [UsageEnv] -> UsageEnv
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 UsageEnv -> UsageEnv -> UsageEnv
addUE [UsageEnv]
ues)) }
where
bndrs :: [Var]
bndrs = ((Var, CoreExpr) -> Var) -> [(Var, CoreExpr)] -> [Var]
forall a b. (a -> b) -> [a] -> [b]
map (Var, CoreExpr) -> Var
forall a b. (a, b) -> a
fst [(Var, CoreExpr)]
pairs
lintCoreExpr e :: CoreExpr
e@(App CoreExpr
_ CoreExpr
_)
| Var Var
fun <- CoreExpr
fun
, Var
fun Var -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
runRWKey
, CoreExpr
arg_ty1 : CoreExpr
arg_ty2 : CoreExpr
arg3 : [CoreExpr]
rest <- [CoreExpr]
args
= do { (LintedType, UsageEnv)
fun_pair1 <- (LintedType, UsageEnv) -> CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreArg (Var -> LintedType
idType Var
fun, UsageEnv
zeroUE) CoreExpr
arg_ty1
; (LintedType
fun_ty2, UsageEnv
ue2) <- (LintedType, UsageEnv) -> CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreArg (LintedType, UsageEnv)
fun_pair1 CoreExpr
arg_ty2
; let lintRunRWCont :: CoreArg -> LintM (LintedType, UsageEnv)
lintRunRWCont :: CoreExpr -> LintM (LintedType, UsageEnv)
lintRunRWCont expr :: CoreExpr
expr@(Lam Var
_ CoreExpr
_) = do
JoinArity -> Maybe Var -> CoreExpr -> LintM (LintedType, UsageEnv)
lintJoinLams JoinArity
1 (Var -> Maybe Var
forall a. a -> Maybe a
Just Var
fun) CoreExpr
expr
lintRunRWCont CoreExpr
other = LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintM a -> LintM a
markAllJoinsBad (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$ CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
other
; (LintedType
arg3_ty, UsageEnv
ue3) <- CoreExpr -> LintM (LintedType, UsageEnv)
lintRunRWCont CoreExpr
arg3
; (LintedType, UsageEnv)
app_ty <- CoreExpr
-> LintedType
-> LintedType
-> UsageEnv
-> UsageEnv
-> LintM (LintedType, UsageEnv)
lintValApp CoreExpr
arg3 LintedType
fun_ty2 LintedType
arg3_ty UsageEnv
ue2 UsageEnv
ue3
; (LintedType, UsageEnv)
-> [CoreExpr] -> LintM (LintedType, UsageEnv)
lintCoreArgs (LintedType, UsageEnv)
app_ty [CoreExpr]
rest }
| Bool
otherwise
= do { (LintedType, UsageEnv)
pair <- CoreExpr -> JoinArity -> LintM (LintedType, UsageEnv)
lintCoreFun CoreExpr
fun ([CoreExpr] -> JoinArity
forall (t :: * -> *) a. Foldable t => t a -> JoinArity
length [CoreExpr]
args)
; (LintedType, UsageEnv)
-> [CoreExpr] -> LintM (LintedType, UsageEnv)
lintCoreArgs (LintedType, UsageEnv)
pair [CoreExpr]
args }
where
(CoreExpr
fun, [CoreExpr]
args) = CoreExpr -> (CoreExpr, [CoreExpr])
forall b. Expr b -> (Expr b, [Expr b])
collectArgs CoreExpr
e
lintCoreExpr (Lam Var
var CoreExpr
expr)
= LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintM a -> LintM a
markAllJoinsBad (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$
Var -> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
lintLambda Var
var (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$ CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
expr
lintCoreExpr (Case CoreExpr
scrut Var
var LintedType
alt_ty [Alt Var]
alts)
= CoreExpr
-> Var -> LintedType -> [Alt Var] -> LintM (LintedType, UsageEnv)
lintCaseExpr CoreExpr
scrut Var
var LintedType
alt_ty [Alt Var]
alts
lintCoreExpr (Type LintedType
ty)
= SDoc -> LintM (LintedType, UsageEnv)
forall a. SDoc -> LintM a
failWithL (String -> SDoc
text String
"Type found as expression" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ty)
lintCoreExpr (Coercion Coercion
co)
= do { Coercion
co' <- LintLocInfo -> LintM Coercion -> LintM Coercion
forall a. LintLocInfo -> LintM a -> LintM a
addLoc (Coercion -> LintLocInfo
InCo Coercion
co) (LintM Coercion -> LintM Coercion)
-> LintM Coercion -> LintM Coercion
forall a b. (a -> b) -> a -> b
$
Coercion -> LintM Coercion
lintCoercion Coercion
co
; (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (Coercion -> LintedType
coercionType Coercion
co', UsageEnv
zeroUE) }
lintIdOcc :: Var -> Int
-> LintM (LintedType, UsageEnv)
lintIdOcc :: Var -> JoinArity -> LintM (LintedType, UsageEnv)
lintIdOcc Var
var JoinArity
nargs
= LintLocInfo
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintLocInfo -> LintM a -> LintM a
addLoc (Var -> LintLocInfo
OccOf Var
var) (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$
do { Bool -> SDoc -> LintM ()
checkL (Var -> Bool
isNonCoVarId Var
var)
(String -> SDoc
text String
"Non term variable" SDoc -> SDoc -> SDoc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
var)
; (Var
bndr, LintedType
linted_bndr_ty) <- Var -> LintM (Var, LintedType)
lookupIdInScope Var
var
; let occ_ty :: LintedType
occ_ty = Var -> LintedType
idType Var
var
bndr_ty :: LintedType
bndr_ty = Var -> LintedType
idType Var
bndr
; LintedType -> LintedType -> SDoc -> LintM ()
ensureEqTys LintedType
occ_ty LintedType
bndr_ty (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
Var -> Var -> LintedType -> LintedType -> SDoc
mkBndrOccTypeMismatchMsg Var
bndr Var
var LintedType
bndr_ty LintedType
occ_ty
; LintFlags
lf <- LintM LintFlags
getLintFlags
; Bool -> LintM () -> LintM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (JoinArity
nargs JoinArity -> JoinArity -> Bool
forall a. Eq a => a -> a -> Bool
/= JoinArity
0 Bool -> Bool -> Bool
&& LintFlags -> StaticPtrCheck
lf_check_static_ptrs LintFlags
lf StaticPtrCheck -> StaticPtrCheck -> Bool
forall a. Eq a => a -> a -> Bool
/= StaticPtrCheck
AllowAnywhere) (LintM () -> LintM ()) -> LintM () -> LintM ()
forall a b. (a -> b) -> a -> b
$
Bool -> SDoc -> LintM ()
checkL (Var -> Name
idName Var
var Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
/= Name
makeStaticName) (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
String -> SDoc
text String
"Found makeStatic nested in an expression"
; Var -> LintM ()
checkDeadIdOcc Var
var
; Var -> JoinArity -> LintM ()
checkJoinOcc Var
var JoinArity
nargs
; UsageEnv
usage <- Var -> LintM UsageEnv
varCallSiteUsage Var
var
; (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (LintedType
linted_bndr_ty, UsageEnv
usage) }
lintCoreFun :: CoreExpr
-> Int
-> LintM (LintedType, UsageEnv)
lintCoreFun :: CoreExpr -> JoinArity -> LintM (LintedType, UsageEnv)
lintCoreFun (Var Var
var) JoinArity
nargs
= Var -> JoinArity -> LintM (LintedType, UsageEnv)
lintIdOcc Var
var JoinArity
nargs
lintCoreFun (Lam Var
var CoreExpr
body) JoinArity
nargs
| JoinArity
nargs JoinArity -> JoinArity -> Bool
forall a. Eq a => a -> a -> Bool
/= JoinArity
0
= Var -> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
lintLambda Var
var (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$ CoreExpr -> JoinArity -> LintM (LintedType, UsageEnv)
lintCoreFun CoreExpr
body (JoinArity
nargs JoinArity -> JoinArity -> JoinArity
forall a. Num a => a -> a -> a
- JoinArity
1)
lintCoreFun CoreExpr
expr JoinArity
nargs
= Bool
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. Bool -> LintM a -> LintM a
markAllJoinsBadIf (JoinArity
nargs JoinArity -> JoinArity -> Bool
forall a. Eq a => a -> a -> Bool
/= JoinArity
0) (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$
CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
expr
lintLambda :: Var -> LintM (Type, UsageEnv) -> LintM (Type, UsageEnv)
lintLambda :: Var -> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
lintLambda Var
var LintM (LintedType, UsageEnv)
lintBody =
LintLocInfo
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintLocInfo -> LintM a -> LintM a
addLoc (Var -> LintLocInfo
LambdaBodyOf Var
var) (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$
BindingSite
-> Var
-> (Var -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv)
forall a. BindingSite -> Var -> (Var -> LintM a) -> LintM a
lintBinder BindingSite
LambdaBind Var
var ((Var -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv))
-> (Var -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$ \ Var
var' ->
do { (LintedType
body_ty, UsageEnv
ue) <- LintM (LintedType, UsageEnv)
lintBody
; UsageEnv
ue' <- UsageEnv -> Var -> LintM UsageEnv
checkLinearity UsageEnv
ue Var
var'
; (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (Var -> LintedType -> LintedType
mkLamType Var
var' LintedType
body_ty, UsageEnv
ue') }
checkDeadIdOcc :: Id -> LintM ()
checkDeadIdOcc :: Var -> LintM ()
checkDeadIdOcc Var
id
| OccInfo -> Bool
isDeadOcc (Var -> OccInfo
idOccInfo Var
id)
= do { Bool
in_case <- LintM Bool
inCasePat
; Bool -> SDoc -> LintM ()
checkL Bool
in_case
(String -> SDoc
text String
"Occurrence of a dead Id" SDoc -> SDoc -> SDoc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
id) }
| Bool
otherwise
= () -> LintM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
lintJoinBndrType :: LintedType
-> LintedId
-> LintM ()
lintJoinBndrType :: LintedType -> Var -> LintM ()
lintJoinBndrType LintedType
body_ty Var
bndr
| Just JoinArity
arity <- Var -> Maybe JoinArity
isJoinId_maybe Var
bndr
, let bndr_ty :: LintedType
bndr_ty = Var -> LintedType
idType Var
bndr
, ([TyCoBinder]
bndrs, LintedType
res) <- LintedType -> ([TyCoBinder], LintedType)
splitPiTys LintedType
bndr_ty
= Bool -> SDoc -> LintM ()
checkL ([TyCoBinder] -> JoinArity
forall (t :: * -> *) a. Foldable t => t a -> JoinArity
length [TyCoBinder]
bndrs JoinArity -> JoinArity -> Bool
forall a. Ord a => a -> a -> Bool
>= JoinArity
arity
Bool -> Bool -> Bool
&& LintedType
body_ty LintedType -> LintedType -> Bool
`eqType` [TyCoBinder] -> LintedType -> LintedType
mkPiTys (JoinArity -> [TyCoBinder] -> [TyCoBinder]
forall a. JoinArity -> [a] -> [a]
drop JoinArity
arity [TyCoBinder]
bndrs) LintedType
res) (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
SDoc -> JoinArity -> SDoc -> SDoc
hang (String -> SDoc
text String
"Join point returns different type than body")
JoinArity
2 ([SDoc] -> SDoc
vcat [ String -> SDoc
text String
"Join bndr:" SDoc -> SDoc -> SDoc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
bndr SDoc -> SDoc -> SDoc
<+> SDoc
dcolon SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Var -> LintedType
idType Var
bndr)
, String -> SDoc
text String
"Join arity:" SDoc -> SDoc -> SDoc
<+> JoinArity -> SDoc
forall a. Outputable a => a -> SDoc
ppr JoinArity
arity
, String -> SDoc
text String
"Body type:" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
body_ty ])
| Bool
otherwise
= () -> LintM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
checkJoinOcc :: Id -> JoinArity -> LintM ()
checkJoinOcc :: Var -> JoinArity -> LintM ()
checkJoinOcc Var
var JoinArity
n_args
| Just JoinArity
join_arity_occ <- Var -> Maybe JoinArity
isJoinId_maybe Var
var
= do { Maybe JoinArity
mb_join_arity_bndr <- Var -> LintM (Maybe JoinArity)
lookupJoinId Var
var
; case Maybe JoinArity
mb_join_arity_bndr of {
Maybe JoinArity
Nothing ->
do { IdSet
join_set <- LintM IdSet
getValidJoins
; SDoc -> LintM ()
addErrL (String -> SDoc
text String
"join set " SDoc -> SDoc -> SDoc
<+> IdSet -> SDoc
forall a. Outputable a => a -> SDoc
ppr IdSet
join_set SDoc -> SDoc -> SDoc
$$
Var -> SDoc
invalidJoinOcc Var
var) } ;
Just JoinArity
join_arity_bndr ->
do { Bool -> SDoc -> LintM ()
checkL (JoinArity
join_arity_bndr JoinArity -> JoinArity -> Bool
forall a. Eq a => a -> a -> Bool
== JoinArity
join_arity_occ) (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
Var -> JoinArity -> JoinArity -> SDoc
mkJoinBndrOccMismatchMsg Var
var JoinArity
join_arity_bndr JoinArity
join_arity_occ
; Bool -> SDoc -> LintM ()
checkL (JoinArity
n_args JoinArity -> JoinArity -> Bool
forall a. Eq a => a -> a -> Bool
== JoinArity
join_arity_occ) (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
Var -> JoinArity -> JoinArity -> SDoc
mkBadJumpMsg Var
var JoinArity
join_arity_occ JoinArity
n_args } } }
| Bool
otherwise
= () -> LintM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
checkLinearity :: UsageEnv -> Var -> LintM UsageEnv
checkLinearity :: UsageEnv -> Var -> LintM UsageEnv
checkLinearity UsageEnv
body_ue Var
lam_var =
case Var -> Maybe LintedType
varMultMaybe Var
lam_var of
Just LintedType
mult -> do Usage -> LintedType -> SDoc -> LintM ()
ensureSubUsage Usage
lhs LintedType
mult (LintedType -> SDoc
forall a. Outputable a => a -> SDoc
err_msg LintedType
mult)
UsageEnv -> LintM UsageEnv
forall (m :: * -> *) a. Monad m => a -> m a
return (UsageEnv -> LintM UsageEnv) -> UsageEnv -> LintM UsageEnv
forall a b. (a -> b) -> a -> b
$ UsageEnv -> Var -> UsageEnv
forall n. NamedThing n => UsageEnv -> n -> UsageEnv
deleteUE UsageEnv
body_ue Var
lam_var
Maybe LintedType
Nothing -> UsageEnv -> LintM UsageEnv
forall (m :: * -> *) a. Monad m => a -> m a
return UsageEnv
body_ue
where
lhs :: Usage
lhs = UsageEnv -> Var -> Usage
forall n. NamedThing n => UsageEnv -> n -> Usage
lookupUE UsageEnv
body_ue Var
lam_var
err_msg :: a -> SDoc
err_msg a
mult = String -> SDoc
text String
"Linearity failure in lambda:" SDoc -> SDoc -> SDoc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
lam_var
SDoc -> SDoc -> SDoc
$$ Usage -> SDoc
forall a. Outputable a => a -> SDoc
ppr Usage
lhs SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"⊈" SDoc -> SDoc -> SDoc
<+> a -> SDoc
forall a. Outputable a => a -> SDoc
ppr a
mult
lintCoreArgs :: (LintedType, UsageEnv) -> [CoreArg] -> LintM (LintedType, UsageEnv)
lintCoreArgs :: (LintedType, UsageEnv)
-> [CoreExpr] -> LintM (LintedType, UsageEnv)
lintCoreArgs (LintedType
fun_ty, UsageEnv
fun_ue) [CoreExpr]
args = ((LintedType, UsageEnv)
-> CoreExpr -> LintM (LintedType, UsageEnv))
-> (LintedType, UsageEnv)
-> [CoreExpr]
-> LintM (LintedType, UsageEnv)
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM (LintedType, UsageEnv) -> CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreArg (LintedType
fun_ty, UsageEnv
fun_ue) [CoreExpr]
args
lintCoreArg :: (LintedType, UsageEnv) -> CoreArg -> LintM (LintedType, UsageEnv)
lintCoreArg :: (LintedType, UsageEnv) -> CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreArg (LintedType
fun_ty, UsageEnv
ue) (Type LintedType
arg_ty)
= do { Bool -> SDoc -> LintM ()
checkL (Bool -> Bool
not (LintedType -> Bool
isCoercionTy LintedType
arg_ty))
(String -> SDoc
text String
"Unnecessary coercion-to-type injection:"
SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
arg_ty)
; LintedType
arg_ty' <- LintedType -> LintM LintedType
lintType LintedType
arg_ty
; LintedType
res <- LintedType -> LintedType -> LintM LintedType
lintTyApp LintedType
fun_ty LintedType
arg_ty'
; (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (LintedType
res, UsageEnv
ue) }
lintCoreArg (LintedType
fun_ty, UsageEnv
fun_ue) CoreExpr
arg
= do { (LintedType
arg_ty, UsageEnv
arg_ue) <- LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintM a -> LintM a
markAllJoinsBad (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$ CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
arg
; LintFlags
flags <- LintM LintFlags
getLintFlags
; Bool -> SDoc -> LintM ()
lintL (Bool -> Bool
not (LintFlags -> Bool
lf_check_levity_poly LintFlags
flags) Bool -> Bool -> Bool
|| Bool -> Bool
not (LintedType -> Bool
isTypeLevPoly LintedType
arg_ty))
(String -> SDoc
text String
"Levity-polymorphic argument:" SDoc -> SDoc -> SDoc
<+>
(CoreExpr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreExpr
arg SDoc -> SDoc -> SDoc
<+> SDoc
dcolon SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
parens (LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
arg_ty SDoc -> SDoc -> SDoc
<+> SDoc
dcolon SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr (HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
arg_ty))))
; Bool -> SDoc -> LintM ()
checkL (Bool -> Bool
not (HasDebugCallStack => LintedType -> Bool
LintedType -> Bool
isUnliftedType LintedType
arg_ty) Bool -> Bool -> Bool
|| CoreExpr -> Bool
exprOkForSpeculation CoreExpr
arg)
(CoreExpr -> SDoc
mkLetAppMsg CoreExpr
arg)
; CoreExpr
-> LintedType
-> LintedType
-> UsageEnv
-> UsageEnv
-> LintM (LintedType, UsageEnv)
lintValApp CoreExpr
arg LintedType
fun_ty LintedType
arg_ty UsageEnv
fun_ue UsageEnv
arg_ue }
lintAltBinders :: UsageEnv
-> Var
-> LintedType
-> LintedType
-> [(Mult, OutVar)]
-> LintM UsageEnv
lintAltBinders :: UsageEnv
-> Var
-> LintedType
-> LintedType
-> [(LintedType, Var)]
-> LintM UsageEnv
lintAltBinders UsageEnv
rhs_ue Var
_case_bndr LintedType
scrut_ty LintedType
con_ty []
= do { LintedType -> LintedType -> SDoc -> LintM ()
ensureEqTys LintedType
con_ty LintedType
scrut_ty (LintedType -> LintedType -> SDoc
mkBadPatMsg LintedType
con_ty LintedType
scrut_ty)
; UsageEnv -> LintM UsageEnv
forall (m :: * -> *) a. Monad m => a -> m a
return UsageEnv
rhs_ue }
lintAltBinders UsageEnv
rhs_ue Var
case_bndr LintedType
scrut_ty LintedType
con_ty ((LintedType
var_w, Var
bndr):[(LintedType, Var)]
bndrs)
| Var -> Bool
isTyVar Var
bndr
= do { LintedType
con_ty' <- LintedType -> LintedType -> LintM LintedType
lintTyApp LintedType
con_ty (Var -> LintedType
mkTyVarTy Var
bndr)
; UsageEnv
-> Var
-> LintedType
-> LintedType
-> [(LintedType, Var)]
-> LintM UsageEnv
lintAltBinders UsageEnv
rhs_ue Var
case_bndr LintedType
scrut_ty LintedType
con_ty' [(LintedType, Var)]
bndrs }
| Bool
otherwise
= do { (LintedType
con_ty', UsageEnv
_) <- CoreExpr
-> LintedType
-> LintedType
-> UsageEnv
-> UsageEnv
-> LintM (LintedType, UsageEnv)
lintValApp (Var -> CoreExpr
forall b. Var -> Expr b
Var Var
bndr) LintedType
con_ty (Var -> LintedType
idType Var
bndr) UsageEnv
zeroUE UsageEnv
zeroUE
; UsageEnv
rhs_ue' <- UsageEnv -> Var -> LintedType -> Var -> LintM UsageEnv
checkCaseLinearity UsageEnv
rhs_ue Var
case_bndr LintedType
var_w Var
bndr
; UsageEnv
-> Var
-> LintedType
-> LintedType
-> [(LintedType, Var)]
-> LintM UsageEnv
lintAltBinders UsageEnv
rhs_ue' Var
case_bndr LintedType
scrut_ty LintedType
con_ty' [(LintedType, Var)]
bndrs }
checkCaseLinearity :: UsageEnv -> Var -> Mult -> Var -> LintM UsageEnv
checkCaseLinearity :: UsageEnv -> Var -> LintedType -> Var -> LintM UsageEnv
checkCaseLinearity UsageEnv
ue Var
case_bndr LintedType
var_w Var
bndr = do
Usage -> LintedType -> SDoc -> LintM ()
ensureSubUsage Usage
lhs LintedType
rhs SDoc
err_msg
SDoc -> LintedType -> LintedType -> LintM ()
lintLinearBinder (Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
bndr) (LintedType
case_bndr_w LintedType -> LintedType -> LintedType
`mkMultMul` LintedType
var_w) (Var -> LintedType
varMult Var
bndr)
UsageEnv -> LintM UsageEnv
forall (m :: * -> *) a. Monad m => a -> m a
return (UsageEnv -> LintM UsageEnv) -> UsageEnv -> LintM UsageEnv
forall a b. (a -> b) -> a -> b
$ UsageEnv -> Var -> UsageEnv
forall n. NamedThing n => UsageEnv -> n -> UsageEnv
deleteUE UsageEnv
ue Var
bndr
where
lhs :: Usage
lhs = Usage
bndr_usage Usage -> Usage -> Usage
`addUsage` (LintedType
var_w LintedType -> Usage -> Usage
`scaleUsage` Usage
case_bndr_usage)
rhs :: LintedType
rhs = LintedType
case_bndr_w LintedType -> LintedType -> LintedType
`mkMultMul` LintedType
var_w
err_msg :: SDoc
err_msg = (String -> SDoc
text String
"Linearity failure in variable:" SDoc -> SDoc -> SDoc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
bndr
SDoc -> SDoc -> SDoc
$$ Usage -> SDoc
forall a. Outputable a => a -> SDoc
ppr Usage
lhs SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"⊈" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
rhs
SDoc -> SDoc -> SDoc
$$ String -> SDoc
text String
"Computed by:"
SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"LHS:" SDoc -> SDoc -> SDoc
<+> SDoc
lhs_formula
SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"RHS:" SDoc -> SDoc -> SDoc
<+> SDoc
rhs_formula)
lhs_formula :: SDoc
lhs_formula = Usage -> SDoc
forall a. Outputable a => a -> SDoc
ppr Usage
bndr_usage SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"+"
SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
parens (Usage -> SDoc
forall a. Outputable a => a -> SDoc
ppr Usage
case_bndr_usage SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"*" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
var_w)
rhs_formula :: SDoc
rhs_formula = LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
case_bndr_w SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"*" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
var_w
case_bndr_w :: LintedType
case_bndr_w = Var -> LintedType
varMult Var
case_bndr
case_bndr_usage :: Usage
case_bndr_usage = UsageEnv -> Var -> Usage
forall n. NamedThing n => UsageEnv -> n -> Usage
lookupUE UsageEnv
ue Var
case_bndr
bndr_usage :: Usage
bndr_usage = UsageEnv -> Var -> Usage
forall n. NamedThing n => UsageEnv -> n -> Usage
lookupUE UsageEnv
ue Var
bndr
lintTyApp :: LintedType -> LintedType -> LintM LintedType
lintTyApp :: LintedType -> LintedType -> LintM LintedType
lintTyApp LintedType
fun_ty LintedType
arg_ty
| Just (Var
tv,LintedType
body_ty) <- LintedType -> Maybe (Var, LintedType)
splitForAllTy_maybe LintedType
fun_ty
= do { Var -> LintedType -> LintM ()
lintTyKind Var
tv LintedType
arg_ty
; InScopeSet
in_scope <- LintM InScopeSet
getInScope
; LintedType -> LintM LintedType
forall (m :: * -> *) a. Monad m => a -> m a
return (InScopeSet -> [Var] -> [LintedType] -> LintedType -> LintedType
substTyWithInScope InScopeSet
in_scope [Var
tv] [LintedType
arg_ty] LintedType
body_ty) }
| Bool
otherwise
= SDoc -> LintM LintedType
forall a. SDoc -> LintM a
failWithL (LintedType -> LintedType -> SDoc
mkTyAppMsg LintedType
fun_ty LintedType
arg_ty)
lintValApp :: CoreExpr -> LintedType -> LintedType -> UsageEnv -> UsageEnv -> LintM (LintedType, UsageEnv)
lintValApp :: CoreExpr
-> LintedType
-> LintedType
-> UsageEnv
-> UsageEnv
-> LintM (LintedType, UsageEnv)
lintValApp CoreExpr
arg LintedType
fun_ty LintedType
arg_ty UsageEnv
fun_ue UsageEnv
arg_ue
| Just (LintedType
w, LintedType
arg_ty', LintedType
res_ty') <- LintedType -> Maybe (LintedType, LintedType, LintedType)
splitFunTy_maybe LintedType
fun_ty
= do { LintedType -> LintedType -> SDoc -> LintM ()
ensureEqTys LintedType
arg_ty' LintedType
arg_ty SDoc
err1
; let app_ue :: UsageEnv
app_ue = UsageEnv -> UsageEnv -> UsageEnv
addUE UsageEnv
fun_ue (LintedType -> UsageEnv -> UsageEnv
scaleUE LintedType
w UsageEnv
arg_ue)
; (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (LintedType
res_ty', UsageEnv
app_ue) }
| Bool
otherwise
= SDoc -> LintM (LintedType, UsageEnv)
forall a. SDoc -> LintM a
failWithL SDoc
err2
where
err1 :: SDoc
err1 = LintedType -> LintedType -> CoreExpr -> SDoc
mkAppMsg LintedType
fun_ty LintedType
arg_ty CoreExpr
arg
err2 :: SDoc
err2 = LintedType -> LintedType -> CoreExpr -> SDoc
mkNonFunAppMsg LintedType
fun_ty LintedType
arg_ty CoreExpr
arg
lintTyKind :: OutTyVar -> LintedType -> LintM ()
lintTyKind :: Var -> LintedType -> LintM ()
lintTyKind Var
tyvar LintedType
arg_ty
= Bool -> LintM () -> LintM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (LintedType
arg_kind LintedType -> LintedType -> Bool
`eqType` LintedType
tyvar_kind) (LintM () -> LintM ()) -> LintM () -> LintM ()
forall a b. (a -> b) -> a -> b
$
SDoc -> LintM ()
addErrL (Var -> LintedType -> SDoc
mkKindErrMsg Var
tyvar LintedType
arg_ty SDoc -> SDoc -> SDoc
$$ (String -> SDoc
text String
"Linted Arg kind:" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
arg_kind))
where
tyvar_kind :: LintedType
tyvar_kind = Var -> LintedType
tyVarKind Var
tyvar
arg_kind :: LintedType
arg_kind = HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
arg_ty
lintCaseExpr :: CoreExpr -> Id -> Type -> [CoreAlt] -> LintM (LintedType, UsageEnv)
lintCaseExpr :: CoreExpr
-> Var -> LintedType -> [Alt Var] -> LintM (LintedType, UsageEnv)
lintCaseExpr CoreExpr
scrut Var
var LintedType
alt_ty [Alt Var]
alts =
do { let e :: CoreExpr
e = CoreExpr -> Var -> LintedType -> [Alt Var] -> CoreExpr
forall b. Expr b -> b -> LintedType -> [Alt b] -> Expr b
Case CoreExpr
scrut Var
var LintedType
alt_ty [Alt Var]
alts
; (LintedType
scrut_ty, UsageEnv
scrut_ue) <- LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintM a -> LintM a
markAllJoinsBad (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$ CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
scrut
; let scrut_mult :: LintedType
scrut_mult = Var -> LintedType
varMult Var
var
; LintedType
alt_ty <- LintLocInfo -> LintM LintedType -> LintM LintedType
forall a. LintLocInfo -> LintM a -> LintM a
addLoc (CoreExpr -> LintLocInfo
CaseTy CoreExpr
scrut) (LintM LintedType -> LintM LintedType)
-> LintM LintedType -> LintM LintedType
forall a b. (a -> b) -> a -> b
$
LintedType -> LintM LintedType
lintValueType LintedType
alt_ty
; LintedType
var_ty <- LintLocInfo -> LintM LintedType -> LintM LintedType
forall a. LintLocInfo -> LintM a -> LintM a
addLoc (Var -> LintLocInfo
IdTy Var
var) (LintM LintedType -> LintM LintedType)
-> LintM LintedType -> LintM LintedType
forall a b. (a -> b) -> a -> b
$
LintedType -> LintM LintedType
lintValueType (Var -> LintedType
idType Var
var)
; let isLitPat :: (AltCon, b, c) -> Bool
isLitPat (LitAlt Literal
_, b
_ , c
_) = Bool
True
isLitPat (AltCon, b, c)
_ = Bool
False
; Bool -> SDoc -> LintM ()
checkL (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ LintedType -> Bool
isFloatingTy LintedType
scrut_ty Bool -> Bool -> Bool
&& (Alt Var -> Bool) -> [Alt Var] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Alt Var -> Bool
forall {b} {c}. (AltCon, b, c) -> Bool
isLitPat [Alt Var]
alts)
(PtrString -> SDoc
ptext (String -> PtrString
sLit (String -> PtrString) -> String -> PtrString
forall a b. (a -> b) -> a -> b
$ String
"Lint warning: Scrutinising floating-point " String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"expression with literal pattern in case " String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"analysis (see #9238).")
SDoc -> SDoc -> SDoc
$$ String -> SDoc
text String
"scrut" SDoc -> SDoc -> SDoc
<+> CoreExpr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreExpr
scrut)
; case LintedType -> Maybe TyCon
tyConAppTyCon_maybe (Var -> LintedType
idType Var
var) of
Just TyCon
tycon
| Bool
debugIsOn
, TyCon -> Bool
isAlgTyCon TyCon
tycon
, Bool -> Bool
not (TyCon -> Bool
isAbstractTyCon TyCon
tycon)
, [DataCon] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (TyCon -> [DataCon]
tyConDataCons TyCon
tycon)
, Bool -> Bool
not (CoreExpr -> Bool
exprIsDeadEnd CoreExpr
scrut)
-> String -> SDoc -> LintM () -> LintM ()
forall a. String -> SDoc -> a -> a
pprTrace String
"Lint warning: case binder's type has no constructors" (Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
var SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Var -> LintedType
idType Var
var))
(LintM () -> LintM ()) -> LintM () -> LintM ()
forall a b. (a -> b) -> a -> b
$ () -> LintM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Maybe TyCon
_otherwise -> () -> LintM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
; TCvSubst
subst <- LintM TCvSubst
getTCvSubst
; LintedType -> LintedType -> SDoc -> LintM ()
ensureEqTys LintedType
var_ty LintedType
scrut_ty (Var -> LintedType -> LintedType -> TCvSubst -> SDoc
mkScrutMsg Var
var LintedType
var_ty LintedType
scrut_ty TCvSubst
subst)
; BindingSite
-> Var
-> (Var -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv)
forall a. BindingSite -> Var -> (Var -> LintM a) -> LintM a
lintBinder BindingSite
CaseBind Var
var ((Var -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv))
-> (Var -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$ \Var
_ ->
do {
; [UsageEnv]
alt_ues <- (Alt Var -> LintM UsageEnv) -> [Alt Var] -> LintM [UsageEnv]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Var
-> LintedType
-> LintedType
-> LintedType
-> Alt Var
-> LintM UsageEnv
lintCoreAlt Var
var LintedType
scrut_ty LintedType
scrut_mult LintedType
alt_ty) [Alt Var]
alts
; let case_ue :: UsageEnv
case_ue = (LintedType -> UsageEnv -> UsageEnv
scaleUE LintedType
scrut_mult UsageEnv
scrut_ue) UsageEnv -> UsageEnv -> UsageEnv
`addUE` [UsageEnv] -> UsageEnv
supUEs [UsageEnv]
alt_ues
; CoreExpr -> LintedType -> [Alt Var] -> LintM ()
checkCaseAlts CoreExpr
e LintedType
scrut_ty [Alt Var]
alts
; (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (LintedType
alt_ty, UsageEnv
case_ue) } }
checkCaseAlts :: CoreExpr -> LintedType -> [CoreAlt] -> LintM ()
checkCaseAlts :: CoreExpr -> LintedType -> [Alt Var] -> LintM ()
checkCaseAlts CoreExpr
e LintedType
ty [Alt Var]
alts =
do { Bool -> SDoc -> LintM ()
checkL ((Alt Var -> Bool) -> [Alt Var] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Alt Var -> Bool
forall {b} {c}. (AltCon, b, c) -> Bool
non_deflt [Alt Var]
con_alts) (CoreExpr -> SDoc
mkNonDefltMsg CoreExpr
e)
; Bool -> SDoc -> LintM ()
checkL ([Alt Var] -> Bool
forall {a} {b}. [(AltCon, a, b)] -> Bool
increasing_tag [Alt Var]
con_alts) (CoreExpr -> SDoc
mkNonIncreasingAltsMsg CoreExpr
e)
; Bool -> SDoc -> LintM ()
checkL (Maybe CoreExpr -> Bool
forall a. Maybe a -> Bool
isJust Maybe CoreExpr
maybe_deflt Bool -> Bool -> Bool
|| Bool -> Bool
not Bool
is_infinite_ty Bool -> Bool -> Bool
|| [Alt Var] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Alt Var]
alts)
(CoreExpr -> SDoc
nonExhaustiveAltsMsg CoreExpr
e) }
where
([Alt Var]
con_alts, Maybe CoreExpr
maybe_deflt) = [Alt Var] -> ([Alt Var], Maybe CoreExpr)
forall a b. [(AltCon, [a], b)] -> ([(AltCon, [a], b)], Maybe b)
findDefault [Alt Var]
alts
increasing_tag :: [(AltCon, a, b)] -> Bool
increasing_tag ((AltCon, a, b)
alt1 : rest :: [(AltCon, a, b)]
rest@( (AltCon, a, b)
alt2 : [(AltCon, a, b)]
_)) = (AltCon, a, b)
alt1 (AltCon, a, b) -> (AltCon, a, b) -> Bool
forall a b. (AltCon, a, b) -> (AltCon, a, b) -> Bool
`ltAlt` (AltCon, a, b)
alt2 Bool -> Bool -> Bool
&& [(AltCon, a, b)] -> Bool
increasing_tag [(AltCon, a, b)]
rest
increasing_tag [(AltCon, a, b)]
_ = Bool
True
non_deflt :: (AltCon, b, c) -> Bool
non_deflt (AltCon
DEFAULT, b
_, c
_) = Bool
False
non_deflt (AltCon, b, c)
_ = Bool
True
is_infinite_ty :: Bool
is_infinite_ty = case LintedType -> Maybe TyCon
tyConAppTyCon_maybe LintedType
ty of
Maybe TyCon
Nothing -> Bool
False
Just TyCon
tycon -> TyCon -> Bool
isPrimTyCon TyCon
tycon
lintAltExpr :: CoreExpr -> LintedType -> LintM UsageEnv
lintAltExpr :: CoreExpr -> LintedType -> LintM UsageEnv
lintAltExpr CoreExpr
expr LintedType
ann_ty
= do { (LintedType
actual_ty, UsageEnv
ue) <- CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
expr
; LintedType -> LintedType -> SDoc -> LintM ()
ensureEqTys LintedType
actual_ty LintedType
ann_ty (CoreExpr -> LintedType -> LintedType -> SDoc
mkCaseAltMsg CoreExpr
expr LintedType
actual_ty LintedType
ann_ty)
; UsageEnv -> LintM UsageEnv
forall (m :: * -> *) a. Monad m => a -> m a
return UsageEnv
ue }
lintCoreAlt :: Var
-> LintedType
-> Mult
-> LintedType
-> CoreAlt
-> LintM UsageEnv
lintCoreAlt :: Var
-> LintedType
-> LintedType
-> LintedType
-> Alt Var
-> LintM UsageEnv
lintCoreAlt Var
_ LintedType
_ LintedType
_ LintedType
alt_ty (AltCon
DEFAULT, [Var]
args, CoreExpr
rhs) =
do { Bool -> SDoc -> LintM ()
lintL ([Var] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Var]
args) ([Var] -> SDoc
mkDefaultArgsMsg [Var]
args)
; CoreExpr -> LintedType -> LintM UsageEnv
lintAltExpr CoreExpr
rhs LintedType
alt_ty }
lintCoreAlt Var
_case_bndr LintedType
scrut_ty LintedType
_ LintedType
alt_ty (LitAlt Literal
lit, [Var]
args, CoreExpr
rhs)
| Literal -> Bool
litIsLifted Literal
lit
= SDoc -> LintM UsageEnv
forall a. SDoc -> LintM a
failWithL SDoc
integerScrutinisedMsg
| Bool
otherwise
= do { Bool -> SDoc -> LintM ()
lintL ([Var] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Var]
args) ([Var] -> SDoc
mkDefaultArgsMsg [Var]
args)
; LintedType -> LintedType -> SDoc -> LintM ()
ensureEqTys LintedType
lit_ty LintedType
scrut_ty (LintedType -> LintedType -> SDoc
mkBadPatMsg LintedType
lit_ty LintedType
scrut_ty)
; CoreExpr -> LintedType -> LintM UsageEnv
lintAltExpr CoreExpr
rhs LintedType
alt_ty }
where
lit_ty :: LintedType
lit_ty = Literal -> LintedType
literalType Literal
lit
lintCoreAlt Var
case_bndr LintedType
scrut_ty LintedType
_scrut_mult LintedType
alt_ty alt :: Alt Var
alt@(DataAlt DataCon
con, [Var]
args, CoreExpr
rhs)
| TyCon -> Bool
isNewTyCon (DataCon -> TyCon
dataConTyCon DataCon
con)
= UsageEnv
zeroUE UsageEnv -> LintM () -> LintM UsageEnv
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ SDoc -> LintM ()
addErrL (LintedType -> Alt Var -> SDoc
mkNewTyDataConAltMsg LintedType
scrut_ty Alt Var
alt)
| Just (TyCon
tycon, [LintedType]
tycon_arg_tys) <- HasDebugCallStack => LintedType -> Maybe (TyCon, [LintedType])
LintedType -> Maybe (TyCon, [LintedType])
splitTyConApp_maybe LintedType
scrut_ty
= LintLocInfo -> LintM UsageEnv -> LintM UsageEnv
forall a. LintLocInfo -> LintM a -> LintM a
addLoc (Alt Var -> LintLocInfo
CaseAlt Alt Var
alt) (LintM UsageEnv -> LintM UsageEnv)
-> LintM UsageEnv -> LintM UsageEnv
forall a b. (a -> b) -> a -> b
$ do
{
Bool -> SDoc -> LintM ()
lintL (TyCon
tycon TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== DataCon -> TyCon
dataConTyCon DataCon
con) (TyCon -> DataCon -> SDoc
mkBadConMsg TyCon
tycon DataCon
con)
; let { con_payload_ty :: LintedType
con_payload_ty = HasDebugCallStack => LintedType -> [LintedType] -> LintedType
LintedType -> [LintedType] -> LintedType
piResultTys (DataCon -> LintedType
dataConRepType DataCon
con) [LintedType]
tycon_arg_tys
; ex_tvs_n :: JoinArity
ex_tvs_n = [Var] -> JoinArity
forall (t :: * -> *) a. Foldable t => t a -> JoinArity
length (DataCon -> [Var]
dataConExTyCoVars DataCon
con)
; multiplicities :: [LintedType]
multiplicities = JoinArity -> LintedType -> [LintedType]
forall a. JoinArity -> a -> [a]
replicate JoinArity
ex_tvs_n LintedType
Many [LintedType] -> [LintedType] -> [LintedType]
forall a. [a] -> [a] -> [a]
++
(Scaled LintedType -> LintedType)
-> [Scaled LintedType] -> [LintedType]
forall a b. (a -> b) -> [a] -> [b]
map Scaled LintedType -> LintedType
forall a. Scaled a -> LintedType
scaledMult (DataCon -> [Scaled LintedType]
dataConRepArgTys DataCon
con) }
; BindingSite -> [Var] -> ([Var] -> LintM UsageEnv) -> LintM UsageEnv
forall a. BindingSite -> [Var] -> ([Var] -> LintM a) -> LintM a
lintBinders BindingSite
CasePatBind [Var]
args (([Var] -> LintM UsageEnv) -> LintM UsageEnv)
-> ([Var] -> LintM UsageEnv) -> LintM UsageEnv
forall a b. (a -> b) -> a -> b
$ \ [Var]
args' -> do
{
UsageEnv
rhs_ue <- CoreExpr -> LintedType -> LintM UsageEnv
lintAltExpr CoreExpr
rhs LintedType
alt_ty
; UsageEnv
rhs_ue' <- LintLocInfo -> LintM UsageEnv -> LintM UsageEnv
forall a. LintLocInfo -> LintM a -> LintM a
addLoc (Alt Var -> LintLocInfo
CasePat Alt Var
alt) (UsageEnv
-> Var
-> LintedType
-> LintedType
-> [(LintedType, Var)]
-> LintM UsageEnv
lintAltBinders UsageEnv
rhs_ue Var
case_bndr LintedType
scrut_ty LintedType
con_payload_ty (String -> [LintedType] -> [Var] -> [(LintedType, Var)]
forall a b. String -> [a] -> [b] -> [(a, b)]
zipEqual String
"lintCoreAlt" [LintedType]
multiplicities [Var]
args'))
; UsageEnv -> LintM UsageEnv
forall (m :: * -> *) a. Monad m => a -> m a
return (UsageEnv -> LintM UsageEnv) -> UsageEnv -> LintM UsageEnv
forall a b. (a -> b) -> a -> b
$ UsageEnv -> Var -> UsageEnv
forall n. NamedThing n => UsageEnv -> n -> UsageEnv
deleteUE UsageEnv
rhs_ue' Var
case_bndr
}
}
| Bool
otherwise
= UsageEnv
zeroUE UsageEnv -> LintM () -> LintM UsageEnv
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ SDoc -> LintM ()
addErrL (LintedType -> Alt Var -> SDoc
mkBadAltMsg LintedType
scrut_ty Alt Var
alt)
lintLinearBinder :: SDoc -> Mult -> Mult -> LintM ()
lintLinearBinder :: SDoc -> LintedType -> LintedType -> LintM ()
lintLinearBinder SDoc
doc LintedType
actual_usage LintedType
described_usage
= LintedType -> LintedType -> SDoc -> LintM ()
ensureSubMult LintedType
actual_usage LintedType
described_usage SDoc
err_msg
where
err_msg :: SDoc
err_msg = (String -> SDoc
text String
"Multiplicity of variable does not agree with its context"
SDoc -> SDoc -> SDoc
$$ SDoc
doc
SDoc -> SDoc -> SDoc
$$ LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
actual_usage
SDoc -> SDoc -> SDoc
$$ String -> SDoc
text String
"Annotation:" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
described_usage)
lintBinders :: BindingSite -> [Var] -> ([Var] -> LintM a) -> LintM a
lintBinders :: forall a. BindingSite -> [Var] -> ([Var] -> LintM a) -> LintM a
lintBinders BindingSite
_ [] [Var] -> LintM a
linterF = [Var] -> LintM a
linterF []
lintBinders BindingSite
site (Var
var:[Var]
vars) [Var] -> LintM a
linterF = BindingSite -> Var -> (Var -> LintM a) -> LintM a
forall a. BindingSite -> Var -> (Var -> LintM a) -> LintM a
lintBinder BindingSite
site Var
var ((Var -> LintM a) -> LintM a) -> (Var -> LintM a) -> LintM a
forall a b. (a -> b) -> a -> b
$ \Var
var' ->
BindingSite -> [Var] -> ([Var] -> LintM a) -> LintM a
forall a. BindingSite -> [Var] -> ([Var] -> LintM a) -> LintM a
lintBinders BindingSite
site [Var]
vars (([Var] -> LintM a) -> LintM a) -> ([Var] -> LintM a) -> LintM a
forall a b. (a -> b) -> a -> b
$ \ [Var]
vars' ->
[Var] -> LintM a
linterF (Var
var'Var -> [Var] -> [Var]
forall a. a -> [a] -> [a]
:[Var]
vars')
lintBinder :: BindingSite -> Var -> (Var -> LintM a) -> LintM a
lintBinder :: forall a. BindingSite -> Var -> (Var -> LintM a) -> LintM a
lintBinder BindingSite
site Var
var Var -> LintM a
linterF
| Var -> Bool
isTyCoVar Var
var = Var -> (Var -> LintM a) -> LintM a
forall a. Var -> (Var -> LintM a) -> LintM a
lintTyCoBndr Var
var Var -> LintM a
linterF
| Bool
otherwise = TopLevelFlag -> BindingSite -> Var -> (Var -> LintM a) -> LintM a
forall a.
TopLevelFlag -> BindingSite -> Var -> (Var -> LintM a) -> LintM a
lintIdBndr TopLevelFlag
NotTopLevel BindingSite
site Var
var Var -> LintM a
linterF
lintTyBndr :: TyVar -> (LintedTyCoVar -> LintM a) -> LintM a
lintTyBndr :: forall a. Var -> (Var -> LintM a) -> LintM a
lintTyBndr = Var -> (Var -> LintM a) -> LintM a
forall a. Var -> (Var -> LintM a) -> LintM a
lintTyCoBndr
lintTyCoBndr :: TyCoVar -> (LintedTyCoVar -> LintM a) -> LintM a
lintTyCoBndr :: forall a. Var -> (Var -> LintM a) -> LintM a
lintTyCoBndr Var
tcv Var -> LintM a
thing_inside
= do { TCvSubst
subst <- LintM TCvSubst
getTCvSubst
; LintedType
kind' <- LintedType -> LintM LintedType
lintType (Var -> LintedType
varType Var
tcv)
; let tcv' :: Var
tcv' = InScopeSet -> Var -> Var
uniqAway (TCvSubst -> InScopeSet
getTCvInScope TCvSubst
subst) (Var -> Var) -> Var -> Var
forall a b. (a -> b) -> a -> b
$
Var -> LintedType -> Var
setVarType Var
tcv LintedType
kind'
subst' :: TCvSubst
subst' = TCvSubst -> Var -> Var -> TCvSubst
extendTCvSubstWithClone TCvSubst
subst Var
tcv Var
tcv'
; Bool -> LintM () -> LintM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Var -> Bool
isCoVar Var
tcv) (LintM () -> LintM ()) -> LintM () -> LintM ()
forall a b. (a -> b) -> a -> b
$
Bool -> SDoc -> LintM ()
lintL (LintedType -> Bool
isCoVarType LintedType
kind')
(String -> SDoc
text String
"CoVar with non-coercion type:" SDoc -> SDoc -> SDoc
<+> Var -> SDoc
pprTyVar Var
tcv)
; TCvSubst -> LintM a -> LintM a
forall a. TCvSubst -> LintM a -> LintM a
updateTCvSubst TCvSubst
subst' (Var -> LintM a
thing_inside Var
tcv') }
lintIdBndrs :: forall a. TopLevelFlag -> [Id] -> ([LintedId] -> LintM a) -> LintM a
lintIdBndrs :: forall a. TopLevelFlag -> [Var] -> ([Var] -> LintM a) -> LintM a
lintIdBndrs TopLevelFlag
top_lvl [Var]
ids [Var] -> LintM a
thing_inside
= [Var] -> ([Var] -> LintM a) -> LintM a
go [Var]
ids [Var] -> LintM a
thing_inside
where
go :: [Id] -> ([Id] -> LintM a) -> LintM a
go :: [Var] -> ([Var] -> LintM a) -> LintM a
go [] [Var] -> LintM a
thing_inside = [Var] -> LintM a
thing_inside []
go (Var
id:[Var]
ids) [Var] -> LintM a
thing_inside = TopLevelFlag -> BindingSite -> Var -> (Var -> LintM a) -> LintM a
forall a.
TopLevelFlag -> BindingSite -> Var -> (Var -> LintM a) -> LintM a
lintIdBndr TopLevelFlag
top_lvl BindingSite
LetBind Var
id ((Var -> LintM a) -> LintM a) -> (Var -> LintM a) -> LintM a
forall a b. (a -> b) -> a -> b
$ \Var
id' ->
[Var] -> ([Var] -> LintM a) -> LintM a
go [Var]
ids (([Var] -> LintM a) -> LintM a) -> ([Var] -> LintM a) -> LintM a
forall a b. (a -> b) -> a -> b
$ \[Var]
ids' ->
[Var] -> LintM a
thing_inside (Var
id' Var -> [Var] -> [Var]
forall a. a -> [a] -> [a]
: [Var]
ids')
lintIdBndr :: TopLevelFlag -> BindingSite
-> InVar -> (OutVar -> LintM a) -> LintM a
lintIdBndr :: forall a.
TopLevelFlag -> BindingSite -> Var -> (Var -> LintM a) -> LintM a
lintIdBndr TopLevelFlag
top_lvl BindingSite
bind_site Var
id Var -> LintM a
thing_inside
= ASSERT2( isId id, ppr id )
do { LintFlags
flags <- LintM LintFlags
getLintFlags
; Bool -> SDoc -> LintM ()
checkL (Bool -> Bool
not (LintFlags -> Bool
lf_check_global_ids LintFlags
flags) Bool -> Bool -> Bool
|| Var -> Bool
isLocalId Var
id)
(String -> SDoc
text String
"Non-local Id binder" SDoc -> SDoc -> SDoc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
id)
; Bool -> SDoc -> LintM ()
checkL (Bool -> Bool
not (Var -> Bool
isExportedId Var
id) Bool -> Bool -> Bool
|| Bool
is_top_lvl)
(Var -> SDoc
mkNonTopExportedMsg Var
id)
; Bool -> SDoc -> LintM ()
checkL (Bool -> Bool
not (Name -> Bool
isExternalName (Var -> Name
Var.varName Var
id)) Bool -> Bool -> Bool
|| Bool
is_top_lvl)
(Var -> SDoc
mkNonTopExternalNameMsg Var
id)
; Bool -> SDoc -> LintM ()
lintL (Var -> Bool
isJoinId Var
id Bool -> Bool -> Bool
|| Bool -> Bool
not (LintFlags -> Bool
lf_check_levity_poly LintFlags
flags)
Bool -> Bool -> Bool
|| Bool -> Bool
not (LintedType -> Bool
isTypeLevPoly LintedType
id_ty)) (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
String -> SDoc
text String
"Levity-polymorphic binder:" SDoc -> SDoc -> SDoc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
id SDoc -> SDoc -> SDoc
<+> SDoc
dcolon SDoc -> SDoc -> SDoc
<+>
SDoc -> SDoc
parens (LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
id_ty SDoc -> SDoc -> SDoc
<+> SDoc
dcolon SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr (HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
id_ty))
; Bool -> LintM () -> LintM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Var -> Bool
isJoinId Var
id) (LintM () -> LintM ()) -> LintM () -> LintM ()
forall a b. (a -> b) -> a -> b
$
Bool -> SDoc -> LintM ()
checkL (Bool -> Bool
not Bool
is_top_lvl Bool -> Bool -> Bool
&& Bool
is_let_bind) (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
Var -> SDoc
mkBadJoinBindMsg Var
id
; Bool -> SDoc -> LintM ()
lintL (Bool -> Bool
not (LintedType -> Bool
isCoVarType LintedType
id_ty))
(String -> SDoc
text String
"Non-CoVar has coercion type" SDoc -> SDoc -> SDoc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
id SDoc -> SDoc -> SDoc
<+> SDoc
dcolon SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
id_ty)
; LintedType
linted_ty <- LintLocInfo -> LintM LintedType -> LintM LintedType
forall a. LintLocInfo -> LintM a -> LintM a
addLoc (Var -> LintLocInfo
IdTy Var
id) (LintedType -> LintM LintedType
lintValueType LintedType
id_ty)
; Var -> LintedType -> LintM a -> LintM a
forall a. Var -> LintedType -> LintM a -> LintM a
addInScopeId Var
id LintedType
linted_ty (LintM a -> LintM a) -> LintM a -> LintM a
forall a b. (a -> b) -> a -> b
$
Var -> LintM a
thing_inside (Var -> LintedType -> Var
setIdType Var
id LintedType
linted_ty) }
where
id_ty :: LintedType
id_ty = Var -> LintedType
idType Var
id
is_top_lvl :: Bool
is_top_lvl = TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl
is_let_bind :: Bool
is_let_bind = case BindingSite
bind_site of
BindingSite
LetBind -> Bool
True
BindingSite
_ -> Bool
False
lintValueType :: Type -> LintM LintedType
lintValueType :: LintedType -> LintM LintedType
lintValueType LintedType
ty
= LintLocInfo -> LintM LintedType -> LintM LintedType
forall a. LintLocInfo -> LintM a -> LintM a
addLoc (LintedType -> LintLocInfo
InType LintedType
ty) (LintM LintedType -> LintM LintedType)
-> LintM LintedType -> LintM LintedType
forall a b. (a -> b) -> a -> b
$
do { LintedType
ty' <- LintedType -> LintM LintedType
lintType LintedType
ty
; let sk :: LintedType
sk = HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
ty'
; Bool -> SDoc -> LintM ()
lintL (LintedType -> Bool
classifiesTypeWithValues LintedType
sk) (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
SDoc -> JoinArity -> SDoc -> SDoc
hang (String -> SDoc
text String
"Ill-kinded type:" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ty)
JoinArity
2 (String -> SDoc
text String
"has kind:" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
sk)
; LintedType -> LintM LintedType
forall (m :: * -> *) a. Monad m => a -> m a
return LintedType
ty' }
checkTyCon :: TyCon -> LintM ()
checkTyCon :: TyCon -> LintM ()
checkTyCon TyCon
tc
= Bool -> SDoc -> LintM ()
checkL (Bool -> Bool
not (TyCon -> Bool
isTcTyCon TyCon
tc)) (String -> SDoc
text String
"Found TcTyCon:" SDoc -> SDoc -> SDoc
<+> TyCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyCon
tc)
lintType :: Type -> LintM LintedType
lintType :: LintedType -> LintM LintedType
lintType (TyVarTy Var
tv)
| Bool -> Bool
not (Var -> Bool
isTyVar Var
tv)
= SDoc -> LintM LintedType
forall a. SDoc -> LintM a
failWithL (Var -> SDoc
mkBadTyVarMsg Var
tv)
| Bool
otherwise
= do { TCvSubst
subst <- LintM TCvSubst
getTCvSubst
; case TCvSubst -> Var -> Maybe LintedType
lookupTyVar TCvSubst
subst Var
tv of
Just LintedType
linted_ty -> LintedType -> LintM LintedType
forall (m :: * -> *) a. Monad m => a -> m a
return LintedType
linted_ty
Maybe LintedType
Nothing | Var
tv Var -> TCvSubst -> Bool
`isInScope` TCvSubst
subst
-> LintedType -> LintM LintedType
forall (m :: * -> *) a. Monad m => a -> m a
return (Var -> LintedType
TyVarTy Var
tv)
| Bool
otherwise
-> SDoc -> LintM LintedType
forall a. SDoc -> LintM a
failWithL (SDoc -> LintM LintedType) -> SDoc -> LintM LintedType
forall a b. (a -> b) -> a -> b
$
SDoc -> JoinArity -> SDoc -> SDoc
hang (String -> SDoc
text String
"The type variable" SDoc -> SDoc -> SDoc
<+> BindingSite -> Var -> SDoc
forall a. OutputableBndr a => BindingSite -> a -> SDoc
pprBndr BindingSite
LetBind Var
tv)
JoinArity
2 (String -> SDoc
text String
"is out of scope")
}
lintType ty :: LintedType
ty@(AppTy LintedType
t1 LintedType
t2)
| TyConApp {} <- LintedType
t1
= SDoc -> LintM LintedType
forall a. SDoc -> LintM a
failWithL (SDoc -> LintM LintedType) -> SDoc -> LintM LintedType
forall a b. (a -> b) -> a -> b
$ String -> SDoc
text String
"TyConApp to the left of AppTy:" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ty
| Bool
otherwise
= do { LintedType
t1' <- LintedType -> LintM LintedType
lintType LintedType
t1
; LintedType
t2' <- LintedType -> LintM LintedType
lintType LintedType
t2
; LintedType -> LintedType -> [LintedType] -> LintM ()
lint_ty_app LintedType
ty (HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
t1') [LintedType
t2']
; LintedType -> LintM LintedType
forall (m :: * -> *) a. Monad m => a -> m a
return (LintedType -> LintedType -> LintedType
AppTy LintedType
t1' LintedType
t2') }
lintType ty :: LintedType
ty@(TyConApp TyCon
tc [LintedType]
tys)
| TyCon -> Bool
isTypeSynonymTyCon TyCon
tc Bool -> Bool -> Bool
|| TyCon -> Bool
isTypeFamilyTyCon TyCon
tc
= do { Bool
report_unsat <- LintFlags -> Bool
lf_report_unsat_syns (LintFlags -> Bool) -> LintM LintFlags -> LintM Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LintM LintFlags
getLintFlags
; Bool -> LintedType -> TyCon -> [LintedType] -> LintM LintedType
lintTySynFamApp Bool
report_unsat LintedType
ty TyCon
tc [LintedType]
tys }
| TyCon -> Bool
isFunTyCon TyCon
tc
, [LintedType]
tys [LintedType] -> JoinArity -> Bool
forall a. [a] -> JoinArity -> Bool
`lengthIs` JoinArity
5
= SDoc -> LintM LintedType
forall a. SDoc -> LintM a
failWithL (SDoc -> JoinArity -> SDoc -> SDoc
hang (String -> SDoc
text String
"Saturated application of (->)") JoinArity
2 (LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ty))
| Bool
otherwise
= do { TyCon -> LintM ()
checkTyCon TyCon
tc
; [LintedType]
tys' <- (LintedType -> LintM LintedType)
-> [LintedType] -> LintM [LintedType]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM LintedType -> LintM LintedType
lintType [LintedType]
tys
; LintedType -> LintedType -> [LintedType] -> LintM ()
lint_ty_app LintedType
ty (TyCon -> LintedType
tyConKind TyCon
tc) [LintedType]
tys'
; LintedType -> LintM LintedType
forall (m :: * -> *) a. Monad m => a -> m a
return (TyCon -> [LintedType] -> LintedType
TyConApp TyCon
tc [LintedType]
tys') }
lintType ty :: LintedType
ty@(FunTy AnonArgFlag
af LintedType
tw LintedType
t1 LintedType
t2)
= do { LintedType
t1' <- LintedType -> LintM LintedType
lintType LintedType
t1
; LintedType
t2' <- LintedType -> LintM LintedType
lintType LintedType
t2
; LintedType
tw' <- LintedType -> LintM LintedType
lintType LintedType
tw
; SDoc -> LintedType -> LintedType -> LintedType -> LintM ()
lintArrow (String -> SDoc
text String
"type or kind" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
quotes (LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ty)) LintedType
t1' LintedType
t2' LintedType
tw'
; LintedType -> LintM LintedType
forall (m :: * -> *) a. Monad m => a -> m a
return (AnonArgFlag -> LintedType -> LintedType -> LintedType -> LintedType
FunTy AnonArgFlag
af LintedType
tw' LintedType
t1' LintedType
t2') }
lintType ty :: LintedType
ty@(ForAllTy (Bndr Var
tcv ArgFlag
vis) LintedType
body_ty)
| Bool -> Bool
not (Var -> Bool
isTyCoVar Var
tcv)
= SDoc -> LintM LintedType
forall a. SDoc -> LintM a
failWithL (String -> SDoc
text String
"Non-Tyvar or Non-Covar bound in type:" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ty)
| Bool
otherwise
= Var -> (Var -> LintM LintedType) -> LintM LintedType
forall a. Var -> (Var -> LintM a) -> LintM a
lintTyCoBndr Var
tcv ((Var -> LintM LintedType) -> LintM LintedType)
-> (Var -> LintM LintedType) -> LintM LintedType
forall a b. (a -> b) -> a -> b
$ \Var
tcv' ->
do { LintedType
body_ty' <- LintedType -> LintM LintedType
lintType LintedType
body_ty
; Var -> LintedType -> LintM ()
lintForAllBody Var
tcv' LintedType
body_ty'
; Bool -> LintM () -> LintM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Var -> Bool
isCoVar Var
tcv) (LintM () -> LintM ()) -> LintM () -> LintM ()
forall a b. (a -> b) -> a -> b
$
Bool -> SDoc -> LintM ()
lintL (Var
tcv Var -> IdSet -> Bool
`elemVarSet` LintedType -> IdSet
tyCoVarsOfType LintedType
body_ty) (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
String -> SDoc
text String
"Covar does not occur in the body:" SDoc -> SDoc -> SDoc
<+> (Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
tcv SDoc -> SDoc -> SDoc
$$ LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
body_ty)
; LintedType -> LintM LintedType
forall (m :: * -> *) a. Monad m => a -> m a
return (VarBndr Var ArgFlag -> LintedType -> LintedType
ForAllTy (Var -> ArgFlag -> VarBndr Var ArgFlag
forall var argf. var -> argf -> VarBndr var argf
Bndr Var
tcv' ArgFlag
vis) LintedType
body_ty') }
lintType ty :: LintedType
ty@(LitTy TyLit
l)
= do { TyLit -> LintM ()
lintTyLit TyLit
l; LintedType -> LintM LintedType
forall (m :: * -> *) a. Monad m => a -> m a
return LintedType
ty }
lintType (CastTy LintedType
ty Coercion
co)
= do { LintedType
ty' <- LintedType -> LintM LintedType
lintType LintedType
ty
; Coercion
co' <- Coercion -> LintM Coercion
lintStarCoercion Coercion
co
; let tyk :: LintedType
tyk = HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
ty'
cok :: LintedType
cok = Coercion -> LintedType
coercionLKind Coercion
co'
; LintedType -> LintedType -> SDoc -> LintM ()
ensureEqTys LintedType
tyk LintedType
cok (LintedType -> Coercion -> LintedType -> LintedType -> SDoc
mkCastTyErr LintedType
ty Coercion
co LintedType
tyk LintedType
cok)
; LintedType -> LintM LintedType
forall (m :: * -> *) a. Monad m => a -> m a
return (LintedType -> Coercion -> LintedType
CastTy LintedType
ty' Coercion
co') }
lintType (CoercionTy Coercion
co)
= do { Coercion
co' <- Coercion -> LintM Coercion
lintCoercion Coercion
co
; LintedType -> LintM LintedType
forall (m :: * -> *) a. Monad m => a -> m a
return (Coercion -> LintedType
CoercionTy Coercion
co') }
lintForAllBody :: LintedTyCoVar -> LintedType -> LintM ()
lintForAllBody :: Var -> LintedType -> LintM ()
lintForAllBody Var
tcv LintedType
body_ty
= do { LintedType -> SDoc -> LintM ()
checkValueType LintedType
body_ty (String -> SDoc
text String
"the body of forall:" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
body_ty)
; let body_kind :: LintedType
body_kind = HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
body_ty
; Bool -> LintM () -> LintM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Var -> Bool
isTyVar Var
tcv) (LintM () -> LintM ()) -> LintM () -> LintM ()
forall a b. (a -> b) -> a -> b
$
case [Var] -> LintedType -> Maybe LintedType
occCheckExpand [Var
tcv] LintedType
body_kind of
Just {} -> () -> LintM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Maybe LintedType
Nothing -> SDoc -> LintM ()
forall a. SDoc -> LintM a
failWithL (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
SDoc -> JoinArity -> SDoc -> SDoc
hang (String -> SDoc
text String
"Variable escape in forall:")
JoinArity
2 ([SDoc] -> SDoc
vcat [ String -> SDoc
text String
"tyvar:" SDoc -> SDoc -> SDoc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
tcv
, String -> SDoc
text String
"type:" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
body_ty
, String -> SDoc
text String
"kind:" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
body_kind ])
}
lintTySynFamApp :: Bool -> InType -> TyCon -> [InType] -> LintM LintedType
lintTySynFamApp :: Bool -> LintedType -> TyCon -> [LintedType] -> LintM LintedType
lintTySynFamApp Bool
report_unsat LintedType
ty TyCon
tc [LintedType]
tys
| Bool
report_unsat
, [LintedType]
tys [LintedType] -> JoinArity -> Bool
forall a. [a] -> JoinArity -> Bool
`lengthLessThan` TyCon -> JoinArity
tyConArity TyCon
tc
= SDoc -> LintM LintedType
forall a. SDoc -> LintM a
failWithL (SDoc -> JoinArity -> SDoc -> SDoc
hang (String -> SDoc
text String
"Un-saturated type application") JoinArity
2 (LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ty))
| Just ([(Var, LintedType)]
tenv, LintedType
rhs, [LintedType]
tys') <- TyCon
-> [LintedType]
-> Maybe ([(Var, LintedType)], LintedType, [LintedType])
forall tyco.
TyCon -> [tyco] -> Maybe ([(Var, tyco)], LintedType, [tyco])
expandSynTyCon_maybe TyCon
tc [LintedType]
tys
, let expanded_ty :: LintedType
expanded_ty = LintedType -> [LintedType] -> LintedType
mkAppTys (HasCallStack => TCvSubst -> LintedType -> LintedType
TCvSubst -> LintedType -> LintedType
substTy ([(Var, LintedType)] -> TCvSubst
mkTvSubstPrs [(Var, LintedType)]
tenv) LintedType
rhs) [LintedType]
tys'
= do {
[LintedType]
tys' <- Bool -> LintM [LintedType] -> LintM [LintedType]
forall a. Bool -> LintM a -> LintM a
setReportUnsat Bool
False ((LintedType -> LintM LintedType)
-> [LintedType] -> LintM [LintedType]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM LintedType -> LintM LintedType
lintType [LintedType]
tys)
; Bool -> LintM () -> LintM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
report_unsat (LintM () -> LintM ()) -> LintM () -> LintM ()
forall a b. (a -> b) -> a -> b
$
do { LintedType
_ <- LintedType -> LintM LintedType
lintType LintedType
expanded_ty
; () -> LintM ()
forall (m :: * -> *) a. Monad m => a -> m a
return () }
; LintedType -> LintedType -> [LintedType] -> LintM ()
lint_ty_app LintedType
ty (TyCon -> LintedType
tyConKind TyCon
tc) [LintedType]
tys'
; LintedType -> LintM LintedType
forall (m :: * -> *) a. Monad m => a -> m a
return (TyCon -> [LintedType] -> LintedType
TyConApp TyCon
tc [LintedType]
tys') }
| Bool
otherwise
= do { [LintedType]
tys' <- (LintedType -> LintM LintedType)
-> [LintedType] -> LintM [LintedType]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM LintedType -> LintM LintedType
lintType [LintedType]
tys
; LintedType -> LintedType -> [LintedType] -> LintM ()
lint_ty_app LintedType
ty (TyCon -> LintedType
tyConKind TyCon
tc) [LintedType]
tys'
; LintedType -> LintM LintedType
forall (m :: * -> *) a. Monad m => a -> m a
return (TyCon -> [LintedType] -> LintedType
TyConApp TyCon
tc [LintedType]
tys') }
checkValueType :: LintedType -> SDoc -> LintM ()
checkValueType :: LintedType -> SDoc -> LintM ()
checkValueType LintedType
ty SDoc
doc
= Bool -> SDoc -> LintM ()
lintL (LintedType -> Bool
classifiesTypeWithValues LintedType
kind)
(String -> SDoc
text String
"Non-*-like kind when *-like expected:" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
kind SDoc -> SDoc -> SDoc
$$
String -> SDoc
text String
"when checking" SDoc -> SDoc -> SDoc
<+> SDoc
doc)
where
kind :: LintedType
kind = HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
ty
lintArrow :: SDoc -> LintedType -> LintedType -> LintedType -> LintM ()
lintArrow :: SDoc -> LintedType -> LintedType -> LintedType -> LintM ()
lintArrow SDoc
what LintedType
t1 LintedType
t2 LintedType
tw
= do { Bool -> LintM () -> LintM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (LintedType -> Bool
classifiesTypeWithValues LintedType
k1) (SDoc -> LintM ()
addErrL (SDoc -> LintedType -> SDoc
forall {a}. Outputable a => SDoc -> a -> SDoc
msg (String -> SDoc
text String
"argument") LintedType
k1))
; Bool -> LintM () -> LintM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (LintedType -> Bool
classifiesTypeWithValues LintedType
k2) (SDoc -> LintM ()
addErrL (SDoc -> LintedType -> SDoc
forall {a}. Outputable a => SDoc -> a -> SDoc
msg (String -> SDoc
text String
"result") LintedType
k2))
; Bool -> LintM () -> LintM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (LintedType -> Bool
isMultiplicityTy LintedType
kw) (SDoc -> LintM ()
addErrL (SDoc -> LintedType -> SDoc
forall {a}. Outputable a => SDoc -> a -> SDoc
msg (String -> SDoc
text String
"multiplicity") LintedType
kw)) }
where
k1 :: LintedType
k1 = HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
t1
k2 :: LintedType
k2 = HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
t2
kw :: LintedType
kw = HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
tw
msg :: SDoc -> a -> SDoc
msg SDoc
ar a
k
= [SDoc] -> SDoc
vcat [ SDoc -> JoinArity -> SDoc -> SDoc
hang (String -> SDoc
text String
"Ill-kinded" SDoc -> SDoc -> SDoc
<+> SDoc
ar)
JoinArity
2 (String -> SDoc
text String
"in" SDoc -> SDoc -> SDoc
<+> SDoc
what)
, SDoc
what SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"kind:" SDoc -> SDoc -> SDoc
<+> a -> SDoc
forall a. Outputable a => a -> SDoc
ppr a
k ]
lint_ty_app :: Type -> LintedKind -> [LintedType] -> LintM ()
lint_ty_app :: LintedType -> LintedType -> [LintedType] -> LintM ()
lint_ty_app LintedType
ty LintedType
k [LintedType]
tys
= SDoc -> LintedType -> [LintedType] -> LintM ()
lint_app (String -> SDoc
text String
"type" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
quotes (LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ty)) LintedType
k [LintedType]
tys
lint_co_app :: Coercion -> LintedKind -> [LintedType] -> LintM ()
lint_co_app :: Coercion -> LintedType -> [LintedType] -> LintM ()
lint_co_app Coercion
ty LintedType
k [LintedType]
tys
= SDoc -> LintedType -> [LintedType] -> LintM ()
lint_app (String -> SDoc
text String
"coercion" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
quotes (Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
ty)) LintedType
k [LintedType]
tys
lintTyLit :: TyLit -> LintM ()
lintTyLit :: TyLit -> LintM ()
lintTyLit (NumTyLit Integer
n)
| Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
0 = () -> LintM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Bool
otherwise = SDoc -> LintM ()
forall a. SDoc -> LintM a
failWithL SDoc
msg
where msg :: SDoc
msg = String -> SDoc
text String
"Negative type literal:" SDoc -> SDoc -> SDoc
<+> Integer -> SDoc
integer Integer
n
lintTyLit (StrTyLit FastString
_) = () -> LintM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
lint_app :: SDoc -> LintedKind -> [LintedType] -> LintM ()
lint_app :: SDoc -> LintedType -> [LintedType] -> LintM ()
lint_app SDoc
doc LintedType
kfn [LintedType]
arg_tys
= do { InScopeSet
in_scope <- LintM InScopeSet
getInScope
; LintedType
_ <- (LintedType -> LintedType -> LintM LintedType)
-> LintedType -> [LintedType] -> LintM LintedType
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldlM (InScopeSet -> LintedType -> LintedType -> LintM LintedType
go_app InScopeSet
in_scope) LintedType
kfn [LintedType]
arg_tys
; () -> LintM ()
forall (m :: * -> *) a. Monad m => a -> m a
return () }
where
fail_msg :: SDoc -> SDoc
fail_msg SDoc
extra = [SDoc] -> SDoc
vcat [ SDoc -> JoinArity -> SDoc -> SDoc
hang (String -> SDoc
text String
"Kind application error in") JoinArity
2 SDoc
doc
, JoinArity -> SDoc -> SDoc
nest JoinArity
2 (String -> SDoc
text String
"Function kind =" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
kfn)
, JoinArity -> SDoc -> SDoc
nest JoinArity
2 (String -> SDoc
text String
"Arg types =" SDoc -> SDoc -> SDoc
<+> [LintedType] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [LintedType]
arg_tys)
, SDoc
extra ]
go_app :: InScopeSet -> LintedType -> LintedType -> LintM LintedType
go_app InScopeSet
in_scope LintedType
kfn LintedType
ta
| Just LintedType
kfn' <- LintedType -> Maybe LintedType
coreView LintedType
kfn
= InScopeSet -> LintedType -> LintedType -> LintM LintedType
go_app InScopeSet
in_scope LintedType
kfn' LintedType
ta
go_app InScopeSet
_ fun_kind :: LintedType
fun_kind@(FunTy AnonArgFlag
_ LintedType
_ LintedType
kfa LintedType
kfb) LintedType
ta
= do { let ka :: LintedType
ka = HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
ta
; Bool -> LintM () -> LintM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (LintedType
ka LintedType -> LintedType -> Bool
`eqType` LintedType
kfa) (LintM () -> LintM ()) -> LintM () -> LintM ()
forall a b. (a -> b) -> a -> b
$
SDoc -> LintM ()
addErrL (SDoc -> SDoc
fail_msg (String -> SDoc
text String
"Fun:" SDoc -> SDoc -> SDoc
<+> (LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
fun_kind SDoc -> SDoc -> SDoc
$$ LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ta SDoc -> SDoc -> SDoc
<+> SDoc
dcolon SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ka)))
; LintedType -> LintM LintedType
forall (m :: * -> *) a. Monad m => a -> m a
return LintedType
kfb }
go_app InScopeSet
in_scope (ForAllTy (Bndr Var
kv ArgFlag
_vis) LintedType
kfn) LintedType
ta
= do { let kv_kind :: LintedType
kv_kind = Var -> LintedType
varType Var
kv
ka :: LintedType
ka = HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
ta
; Bool -> LintM () -> LintM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (LintedType
ka LintedType -> LintedType -> Bool
`eqType` LintedType
kv_kind) (LintM () -> LintM ()) -> LintM () -> LintM ()
forall a b. (a -> b) -> a -> b
$
SDoc -> LintM ()
addErrL (SDoc -> SDoc
fail_msg (String -> SDoc
text String
"Forall:" SDoc -> SDoc -> SDoc
<+> (Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
kv SDoc -> SDoc -> SDoc
$$ LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
kv_kind SDoc -> SDoc -> SDoc
$$
LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ta SDoc -> SDoc -> SDoc
<+> SDoc
dcolon SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ka)))
; LintedType -> LintM LintedType
forall (m :: * -> *) a. Monad m => a -> m a
return (LintedType -> LintM LintedType) -> LintedType -> LintM LintedType
forall a b. (a -> b) -> a -> b
$ HasCallStack => TCvSubst -> LintedType -> LintedType
TCvSubst -> LintedType -> LintedType
substTy (TCvSubst -> Var -> LintedType -> TCvSubst
extendTCvSubst (InScopeSet -> TCvSubst
mkEmptyTCvSubst InScopeSet
in_scope) Var
kv LintedType
ta) LintedType
kfn }
go_app InScopeSet
_ LintedType
kfn LintedType
ta
= SDoc -> LintM LintedType
forall a. SDoc -> LintM a
failWithL (SDoc -> SDoc
fail_msg (String -> SDoc
text String
"Not a fun:" SDoc -> SDoc -> SDoc
<+> (LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
kfn SDoc -> SDoc -> SDoc
$$ LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ta)))
lintCoreRule :: OutVar -> LintedType -> CoreRule -> LintM ()
lintCoreRule :: Var -> LintedType -> CoreRule -> LintM ()
lintCoreRule Var
_ LintedType
_ (BuiltinRule {})
= () -> LintM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
lintCoreRule Var
fun LintedType
fun_ty rule :: CoreRule
rule@(Rule { ru_name :: CoreRule -> FastString
ru_name = FastString
name, ru_bndrs :: CoreRule -> [Var]
ru_bndrs = [Var]
bndrs
, ru_args :: CoreRule -> [CoreExpr]
ru_args = [CoreExpr]
args, ru_rhs :: CoreRule -> CoreExpr
ru_rhs = CoreExpr
rhs })
= BindingSite -> [Var] -> ([Var] -> LintM ()) -> LintM ()
forall a. BindingSite -> [Var] -> ([Var] -> LintM a) -> LintM a
lintBinders BindingSite
LambdaBind [Var]
bndrs (([Var] -> LintM ()) -> LintM ())
-> ([Var] -> LintM ()) -> LintM ()
forall a b. (a -> b) -> a -> b
$ \ [Var]
_ ->
do { (LintedType
lhs_ty, UsageEnv
_) <- (LintedType, UsageEnv)
-> [CoreExpr] -> LintM (LintedType, UsageEnv)
lintCoreArgs (LintedType
fun_ty, UsageEnv
zeroUE) [CoreExpr]
args
; (LintedType
rhs_ty, UsageEnv
_) <- case Var -> Maybe JoinArity
isJoinId_maybe Var
fun of
Just JoinArity
join_arity
-> do { Bool -> SDoc -> LintM ()
checkL ([CoreExpr]
args [CoreExpr] -> JoinArity -> Bool
forall a. [a] -> JoinArity -> Bool
`lengthIs` JoinArity
join_arity) (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
Var -> JoinArity -> CoreRule -> SDoc
mkBadJoinPointRuleMsg Var
fun JoinArity
join_arity CoreRule
rule
; CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
rhs }
Maybe JoinArity
_ -> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintM a -> LintM a
markAllJoinsBad (LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv))
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a b. (a -> b) -> a -> b
$ CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
rhs
; LintedType -> LintedType -> SDoc -> LintM ()
ensureEqTys LintedType
lhs_ty LintedType
rhs_ty (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
(SDoc
rule_doc SDoc -> SDoc -> SDoc
<+> [SDoc] -> SDoc
vcat [ String -> SDoc
text String
"lhs type:" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
lhs_ty
, String -> SDoc
text String
"rhs type:" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
rhs_ty
, String -> SDoc
text String
"fun_ty:" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
fun_ty ])
; let bad_bndrs :: [Var]
bad_bndrs = (Var -> Bool) -> [Var] -> [Var]
forall a. (a -> Bool) -> [a] -> [a]
filter Var -> Bool
is_bad_bndr [Var]
bndrs
; Bool -> SDoc -> LintM ()
checkL ([Var] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Var]
bad_bndrs)
(SDoc
rule_doc SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"unbound" SDoc -> SDoc -> SDoc
<+> [Var] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Var]
bad_bndrs)
}
where
rule_doc :: SDoc
rule_doc = String -> SDoc
text String
"Rule" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
doubleQuotes (FastString -> SDoc
ftext FastString
name) SDoc -> SDoc -> SDoc
<> SDoc
colon
lhs_fvs :: IdSet
lhs_fvs = [CoreExpr] -> IdSet
exprsFreeVars [CoreExpr]
args
rhs_fvs :: IdSet
rhs_fvs = CoreExpr -> IdSet
exprFreeVars CoreExpr
rhs
is_bad_bndr :: Var -> Bool
is_bad_bndr :: Var -> Bool
is_bad_bndr Var
bndr = Bool -> Bool
not (Var
bndr Var -> IdSet -> Bool
`elemVarSet` IdSet
lhs_fvs)
Bool -> Bool -> Bool
&& Var
bndr Var -> IdSet -> Bool
`elemVarSet` IdSet
rhs_fvs
Bool -> Bool -> Bool
&& Maybe Coercion -> Bool
forall a. Maybe a -> Bool
isNothing (Var -> Maybe Coercion
isReflCoVar_maybe Var
bndr)
lintStarCoercion :: InCoercion -> LintM LintedCoercion
lintStarCoercion :: Coercion -> LintM Coercion
lintStarCoercion Coercion
g
= do { Coercion
g' <- Coercion -> LintM Coercion
lintCoercion Coercion
g
; let Pair LintedType
t1 LintedType
t2 = Coercion -> Pair LintedType
coercionKind Coercion
g'
; LintedType -> SDoc -> LintM ()
checkValueType LintedType
t1 (String -> SDoc
text String
"the kind of the left type in" SDoc -> SDoc -> SDoc
<+> Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
g)
; LintedType -> SDoc -> LintM ()
checkValueType LintedType
t2 (String -> SDoc
text String
"the kind of the right type in" SDoc -> SDoc -> SDoc
<+> Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
g)
; Coercion -> Role -> Role -> LintM ()
forall thing. Outputable thing => thing -> Role -> Role -> LintM ()
lintRole Coercion
g Role
Nominal (Coercion -> Role
coercionRole Coercion
g)
; Coercion -> LintM Coercion
forall (m :: * -> *) a. Monad m => a -> m a
return Coercion
g' }
lintCoercion :: InCoercion -> LintM LintedCoercion
lintCoercion :: Coercion -> LintM Coercion
lintCoercion (CoVarCo Var
cv)
| Bool -> Bool
not (Var -> Bool
isCoVar Var
cv)
= SDoc -> LintM Coercion
forall a. SDoc -> LintM a
failWithL (SDoc -> JoinArity -> SDoc -> SDoc
hang (String -> SDoc
text String
"Bad CoVarCo:" SDoc -> SDoc -> SDoc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
cv)
JoinArity
2 (String -> SDoc
text String
"With offending type:" SDoc -> SDoc -> SDoc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Var -> LintedType
varType Var
cv)))
| Bool
otherwise
= do { TCvSubst
subst <- LintM TCvSubst
getTCvSubst
; case TCvSubst -> Var -> Maybe Coercion
lookupCoVar TCvSubst
subst Var
cv of
Just Coercion
linted_co -> Coercion -> LintM Coercion
forall (m :: * -> *) a. Monad m => a -> m a
return Coercion
linted_co ;
Maybe Coercion
Nothing
| Var
cv Var -> TCvSubst -> Bool
`isInScope` TCvSubst
subst
-> Coercion -> LintM Coercion
forall (m :: * -> *) a. Monad m => a -> m a
return (Var -> Coercion
CoVarCo Var
cv)
| Bool
otherwise
->
SDoc -> LintM Coercion
forall a. SDoc -> LintM a
failWithL (SDoc -> LintM Coercion) -> SDoc -> LintM Coercion
forall a b. (a -> b) -> a -> b
$
SDoc -> JoinArity -> SDoc -> SDoc
hang (String -> SDoc
text String
"The coercion variable" SDoc -> SDoc -> SDoc
<+> BindingSite -> Var -> SDoc
forall a. OutputableBndr a => BindingSite -> a -> SDoc
pprBndr BindingSite
LetBind Var
cv)
JoinArity
2 (String -> SDoc
text String
"is out of scope")
}
lintCoercion (Refl LintedType
ty)
= do { LintedType
ty' <- LintedType -> LintM LintedType
lintType LintedType
ty
; Coercion -> LintM Coercion
forall (m :: * -> *) a. Monad m => a -> m a
return (LintedType -> Coercion
Refl LintedType
ty') }
lintCoercion (GRefl Role
r LintedType
ty MCoercion
MRefl)
= do { LintedType
ty' <- LintedType -> LintM LintedType
lintType LintedType
ty
; Coercion -> LintM Coercion
forall (m :: * -> *) a. Monad m => a -> m a
return (Role -> LintedType -> MCoercion -> Coercion
GRefl Role
r LintedType
ty' MCoercion
MRefl) }
lintCoercion (GRefl Role
r LintedType
ty (MCo Coercion
co))
= do { LintedType
ty' <- LintedType -> LintM LintedType
lintType LintedType
ty
; Coercion
co' <- Coercion -> LintM Coercion
lintCoercion Coercion
co
; let tk :: LintedType
tk = HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
ty'
tl :: LintedType
tl = Coercion -> LintedType
coercionLKind Coercion
co'
; LintedType -> LintedType -> SDoc -> LintM ()
ensureEqTys LintedType
tk LintedType
tl (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
SDoc -> JoinArity -> SDoc -> SDoc
hang (String -> SDoc
text String
"GRefl coercion kind mis-match:" SDoc -> SDoc -> SDoc
<+> Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co)
JoinArity
2 ([SDoc] -> SDoc
vcat [LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ty', LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
tk, LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
tl])
; Coercion -> Role -> Role -> LintM ()
forall thing. Outputable thing => thing -> Role -> Role -> LintM ()
lintRole Coercion
co' Role
Nominal (Coercion -> Role
coercionRole Coercion
co')
; Coercion -> LintM Coercion
forall (m :: * -> *) a. Monad m => a -> m a
return (Role -> LintedType -> MCoercion -> Coercion
GRefl Role
r LintedType
ty' (Coercion -> MCoercion
MCo Coercion
co')) }
lintCoercion co :: Coercion
co@(TyConAppCo Role
r TyCon
tc [Coercion]
cos)
| TyCon
tc TyCon -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
funTyConKey
, [Coercion
_w, Coercion
_rep1,Coercion
_rep2,Coercion
_co1,Coercion
_co2] <- [Coercion]
cos
= SDoc -> LintM Coercion
forall a. SDoc -> LintM a
failWithL (String -> SDoc
text String
"Saturated TyConAppCo (->):" SDoc -> SDoc -> SDoc
<+> Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co)
| Just {} <- TyCon -> Maybe ([Var], LintedType)
synTyConDefn_maybe TyCon
tc
= SDoc -> LintM Coercion
forall a. SDoc -> LintM a
failWithL (String -> SDoc
text String
"Synonym in TyConAppCo:" SDoc -> SDoc -> SDoc
<+> Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co)
| Bool
otherwise
= do { TyCon -> LintM ()
checkTyCon TyCon
tc
; [Coercion]
cos' <- (Coercion -> LintM Coercion) -> [Coercion] -> LintM [Coercion]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Coercion -> LintM Coercion
lintCoercion [Coercion]
cos
; let ([Pair LintedType]
co_kinds, [Role]
co_roles) = [(Pair LintedType, Role)] -> ([Pair LintedType], [Role])
forall a b. [(a, b)] -> ([a], [b])
unzip ((Coercion -> (Pair LintedType, Role))
-> [Coercion] -> [(Pair LintedType, Role)]
forall a b. (a -> b) -> [a] -> [b]
map Coercion -> (Pair LintedType, Role)
coercionKindRole [Coercion]
cos')
; Coercion -> LintedType -> [LintedType] -> LintM ()
lint_co_app Coercion
co (TyCon -> LintedType
tyConKind TyCon
tc) ((Pair LintedType -> LintedType)
-> [Pair LintedType] -> [LintedType]
forall a b. (a -> b) -> [a] -> [b]
map Pair LintedType -> LintedType
forall a. Pair a -> a
pFst [Pair LintedType]
co_kinds)
; Coercion -> LintedType -> [LintedType] -> LintM ()
lint_co_app Coercion
co (TyCon -> LintedType
tyConKind TyCon
tc) ((Pair LintedType -> LintedType)
-> [Pair LintedType] -> [LintedType]
forall a b. (a -> b) -> [a] -> [b]
map Pair LintedType -> LintedType
forall a. Pair a -> a
pSnd [Pair LintedType]
co_kinds)
; (Role -> Role -> LintM ()) -> [Role] -> [Role] -> LintM ()
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m ()
zipWithM_ (Coercion -> Role -> Role -> LintM ()
forall thing. Outputable thing => thing -> Role -> Role -> LintM ()
lintRole Coercion
co) (Role -> TyCon -> [Role]
tyConRolesX Role
r TyCon
tc) [Role]
co_roles
; Coercion -> LintM Coercion
forall (m :: * -> *) a. Monad m => a -> m a
return (Role -> TyCon -> [Coercion] -> Coercion
TyConAppCo Role
r TyCon
tc [Coercion]
cos') }
lintCoercion co :: Coercion
co@(AppCo Coercion
co1 Coercion
co2)
| TyConAppCo {} <- Coercion
co1
= SDoc -> LintM Coercion
forall a. SDoc -> LintM a
failWithL (String -> SDoc
text String
"TyConAppCo to the left of AppCo:" SDoc -> SDoc -> SDoc
<+> Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co)
| Just (TyConApp {}, Role
_) <- Coercion -> Maybe (LintedType, Role)
isReflCo_maybe Coercion
co1
= SDoc -> LintM Coercion
forall a. SDoc -> LintM a
failWithL (String -> SDoc
text String
"Refl (TyConApp ...) to the left of AppCo:" SDoc -> SDoc -> SDoc
<+> Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co)
| Bool
otherwise
= do { Coercion
co1' <- Coercion -> LintM Coercion
lintCoercion Coercion
co1
; Coercion
co2' <- Coercion -> LintM Coercion
lintCoercion Coercion
co2
; let (Pair LintedType
lk1 LintedType
rk1, Role
r1) = Coercion -> (Pair LintedType, Role)
coercionKindRole Coercion
co1'
(Pair LintedType
lk2 LintedType
rk2, Role
r2) = Coercion -> (Pair LintedType, Role)
coercionKindRole Coercion
co2'
; Coercion -> LintedType -> [LintedType] -> LintM ()
lint_co_app Coercion
co (HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
lk1) [LintedType
lk2]
; Coercion -> LintedType -> [LintedType] -> LintM ()
lint_co_app Coercion
co (HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
rk1) [LintedType
rk2]
; if Role
r1 Role -> Role -> Bool
forall a. Eq a => a -> a -> Bool
== Role
Phantom
then Bool -> SDoc -> LintM ()
lintL (Role
r2 Role -> Role -> Bool
forall a. Eq a => a -> a -> Bool
== Role
Phantom Bool -> Bool -> Bool
|| Role
r2 Role -> Role -> Bool
forall a. Eq a => a -> a -> Bool
== Role
Nominal)
(String -> SDoc
text String
"Second argument in AppCo cannot be R:" SDoc -> SDoc -> SDoc
$$
Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co)
else Coercion -> Role -> Role -> LintM ()
forall thing. Outputable thing => thing -> Role -> Role -> LintM ()
lintRole Coercion
co Role
Nominal Role
r2
; Coercion -> LintM Coercion
forall (m :: * -> *) a. Monad m => a -> m a
return (Coercion -> Coercion -> Coercion
AppCo Coercion
co1' Coercion
co2') }
lintCoercion co :: Coercion
co@(ForAllCo Var
tcv Coercion
kind_co Coercion
body_co)
| Bool -> Bool
not (Var -> Bool
isTyCoVar Var
tcv)
= SDoc -> LintM Coercion
forall a. SDoc -> LintM a
failWithL (String -> SDoc
text String
"Non tyco binder in ForAllCo:" SDoc -> SDoc -> SDoc
<+> Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co)
| Bool
otherwise
= do { Coercion
kind_co' <- Coercion -> LintM Coercion
lintStarCoercion Coercion
kind_co
; Var -> (Var -> LintM Coercion) -> LintM Coercion
forall a. Var -> (Var -> LintM a) -> LintM a
lintTyCoBndr Var
tcv ((Var -> LintM Coercion) -> LintM Coercion)
-> (Var -> LintM Coercion) -> LintM Coercion
forall a b. (a -> b) -> a -> b
$ \Var
tcv' ->
do { Coercion
body_co' <- Coercion -> LintM Coercion
lintCoercion Coercion
body_co
; LintedType -> LintedType -> SDoc -> LintM ()
ensureEqTys (Var -> LintedType
varType Var
tcv') (Coercion -> LintedType
coercionLKind Coercion
kind_co') (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
String -> SDoc
text String
"Kind mis-match in ForallCo" SDoc -> SDoc -> SDoc
<+> Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co
; let Pair LintedType
lty LintedType
rty = Coercion -> Pair LintedType
coercionKind Coercion
body_co'
; Var -> LintedType -> LintM ()
lintForAllBody Var
tcv' LintedType
lty
; Var -> LintedType -> LintM ()
lintForAllBody Var
tcv' LintedType
rty
; Bool -> LintM () -> LintM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Var -> Bool
isCoVar Var
tcv) (LintM () -> LintM ()) -> LintM () -> LintM ()
forall a b. (a -> b) -> a -> b
$
Bool -> SDoc -> LintM ()
lintL (Var -> Coercion -> Bool
almostDevoidCoVarOfCo Var
tcv Coercion
body_co) (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
String -> SDoc
text String
"Covar can only appear in Refl and GRefl: " SDoc -> SDoc -> SDoc
<+> Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co
; Coercion -> LintM Coercion
forall (m :: * -> *) a. Monad m => a -> m a
return (Var -> Coercion -> Coercion -> Coercion
ForAllCo Var
tcv' Coercion
kind_co' Coercion
body_co') } }
lintCoercion co :: Coercion
co@(FunCo Role
r Coercion
cow Coercion
co1 Coercion
co2)
= do { Coercion
co1' <- Coercion -> LintM Coercion
lintCoercion Coercion
co1
; Coercion
co2' <- Coercion -> LintM Coercion
lintCoercion Coercion
co2
; Coercion
cow' <- Coercion -> LintM Coercion
lintCoercion Coercion
cow
; let Pair LintedType
lt1 LintedType
rt1 = Coercion -> Pair LintedType
coercionKind Coercion
co1
Pair LintedType
lt2 LintedType
rt2 = Coercion -> Pair LintedType
coercionKind Coercion
co2
Pair LintedType
ltw LintedType
rtw = Coercion -> Pair LintedType
coercionKind Coercion
cow
; SDoc -> LintedType -> LintedType -> LintedType -> LintM ()
lintArrow (String -> SDoc
text String
"coercion" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
quotes (Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co)) LintedType
lt1 LintedType
lt2 LintedType
ltw
; SDoc -> LintedType -> LintedType -> LintedType -> LintM ()
lintArrow (String -> SDoc
text String
"coercion" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
quotes (Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co)) LintedType
rt1 LintedType
rt2 LintedType
rtw
; Coercion -> Role -> Role -> LintM ()
forall thing. Outputable thing => thing -> Role -> Role -> LintM ()
lintRole Coercion
co1 Role
r (Coercion -> Role
coercionRole Coercion
co1)
; Coercion -> Role -> Role -> LintM ()
forall thing. Outputable thing => thing -> Role -> Role -> LintM ()
lintRole Coercion
co2 Role
r (Coercion -> Role
coercionRole Coercion
co2)
; LintedType -> LintedType -> SDoc -> LintM ()
ensureEqTys (HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
ltw) LintedType
multiplicityTy (String -> SDoc
text String
"coercion" SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
quotes (Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co))
; LintedType -> LintedType -> SDoc -> LintM ()
ensureEqTys (HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
rtw) LintedType
multiplicityTy (String -> SDoc
text String
"coercion" SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
quotes (Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co))
; let expected_mult_role :: Role
expected_mult_role = case Role
r of
Role
Phantom -> Role
Phantom
Role
_ -> Role
Nominal
; Coercion -> Role -> Role -> LintM ()
forall thing. Outputable thing => thing -> Role -> Role -> LintM ()
lintRole Coercion
cow Role
expected_mult_role (Coercion -> Role
coercionRole Coercion
cow)
; Coercion -> LintM Coercion
forall (m :: * -> *) a. Monad m => a -> m a
return (Role -> Coercion -> Coercion -> Coercion -> Coercion
FunCo Role
r Coercion
cow' Coercion
co1' Coercion
co2') }
lintCoercion co :: Coercion
co@(UnivCo UnivCoProvenance
prov Role
r LintedType
ty1 LintedType
ty2)
= do { LintedType
ty1' <- LintedType -> LintM LintedType
lintType LintedType
ty1
; LintedType
ty2' <- LintedType -> LintM LintedType
lintType LintedType
ty2
; let k1 :: LintedType
k1 = HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
ty1'
k2 :: LintedType
k2 = HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
ty2'
; UnivCoProvenance
prov' <- LintedType
-> LintedType -> UnivCoProvenance -> LintM UnivCoProvenance
lint_prov LintedType
k1 LintedType
k2 UnivCoProvenance
prov
; Bool -> LintM () -> LintM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Role
r Role -> Role -> Bool
forall a. Eq a => a -> a -> Bool
/= Role
Phantom Bool -> Bool -> Bool
&&