{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE UnboxedTuples #-}
module GHC.Core.Lint (
LintPassResultConfig (..),
LintFlags (..),
StaticPtrCheck (..),
LintConfig (..),
WarnsAndErrs,
lintCoreBindings', lintUnfolding,
lintPassResult, lintExpr,
lintAnnots, lintAxioms,
EndPassConfig (..),
endPassIO,
displayLintResults, dumpPassResult
) where
import GHC.Prelude
import GHC.Driver.DynFlags
import GHC.Tc.Utils.TcType
( ConcreteTvOrigin(..), ConcreteTyVars
, isFloatingPrimTy, isTyFamFree )
import GHC.Tc.Types.Origin
( FixedRuntimeRepOrigin(..) )
import GHC.Unit.Module.ModGuts
import GHC.Platform
import GHC.Core
import GHC.Core.FVs
import GHC.Core.Utils
import GHC.Core.Stats ( coreBindsStats )
import GHC.Core.DataCon
import GHC.Core.Ppr
import GHC.Core.Coercion
import GHC.Core.Type as Type
import GHC.Core.Predicate( isCoVarType )
import GHC.Core.Multiplicity
import GHC.Core.UsageEnv
import GHC.Core.TyCo.Rep
import GHC.Core.TyCo.Compare ( eqType, eqTypes, eqTypeIgnoringMultiplicity, eqForAllVis )
import GHC.Core.TyCo.Subst
import GHC.Core.TyCo.FVs
import GHC.Core.TyCo.Ppr
import GHC.Core.TyCon as TyCon
import GHC.Core.Coercion.Axiom
import GHC.Core.FamInstEnv( compatibleBranches )
import GHC.Core.Unify
import GHC.Core.Opt.Arity ( typeArity, exprIsDeadEnd )
import GHC.Core.Opt.Monad
import GHC.Types.Literal
import GHC.Types.Var as Var
import GHC.Types.Var.Env
import GHC.Types.Var.Set
import GHC.Types.Name
import GHC.Types.Name.Env
import GHC.Types.Id
import GHC.Types.Id.Info
import GHC.Types.SrcLoc
import GHC.Types.Tickish
import GHC.Types.Unique.FM ( isNullUFM, sizeUFM )
import GHC.Types.RepType
import GHC.Types.Basic
import GHC.Types.Demand ( splitDmdSig, isDeadEndDiv )
import GHC.Builtin.Names
import GHC.Builtin.Types.Prim
import GHC.Builtin.Types ( multiplicityTy )
import GHC.Data.Bag
import GHC.Data.List.SetOps
import GHC.Utils.Monad
import GHC.Utils.Outputable as Outputable
import GHC.Utils.Panic
import GHC.Utils.Constants (debugIsOn)
import GHC.Utils.Misc
import GHC.Utils.Error
import qualified GHC.Utils.Error as Err
import GHC.Utils.Logger
import Control.Monad
import Data.Foldable ( for_, toList )
import Data.List.NonEmpty ( NonEmpty(..), groupWith )
import Data.List ( partition )
import Data.Maybe
import Data.IntMap.Strict ( IntMap )
import qualified Data.IntMap.Strict as IntMap ( lookup, keys, empty, fromList )
import GHC.Data.Pair
import GHC.Base (oneShot)
import GHC.Data.Unboxed
data EndPassConfig = EndPassConfig
{ EndPassConfig -> Bool
ep_dumpCoreSizes :: !Bool
, EndPassConfig -> Maybe LintPassResultConfig
ep_lintPassResult :: !(Maybe LintPassResultConfig)
, EndPassConfig -> NamePprCtx
ep_namePprCtx :: !NamePprCtx
, EndPassConfig -> Maybe DumpFlag
ep_dumpFlag :: !(Maybe DumpFlag)
, EndPassConfig -> SDoc
ep_prettyPass :: !SDoc
, EndPassConfig -> SDoc
ep_passDetails :: !SDoc
}
endPassIO :: Logger
-> EndPassConfig
-> CoreProgram -> [CoreRule]
-> IO ()
endPassIO :: Logger -> EndPassConfig -> CoreProgram -> [CoreRule] -> IO ()
endPassIO Logger
logger EndPassConfig
cfg CoreProgram
binds [CoreRule]
rules
= do { Logger
-> Bool
-> NamePprCtx
-> Maybe DumpFlag
-> String
-> SDoc
-> CoreProgram
-> [CoreRule]
-> IO ()
dumpPassResult Logger
logger (EndPassConfig -> Bool
ep_dumpCoreSizes EndPassConfig
cfg) (EndPassConfig -> NamePprCtx
ep_namePprCtx EndPassConfig
cfg) Maybe DumpFlag
mb_flag
(SDocContext -> SDoc -> String
renderWithContext SDocContext
defaultSDocContext (EndPassConfig -> SDoc
ep_prettyPass EndPassConfig
cfg))
(EndPassConfig -> SDoc
ep_passDetails EndPassConfig
cfg) CoreProgram
binds [CoreRule]
rules
; Maybe LintPassResultConfig
-> (LintPassResultConfig -> IO ()) -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (EndPassConfig -> Maybe LintPassResultConfig
ep_lintPassResult EndPassConfig
cfg) ((LintPassResultConfig -> IO ()) -> IO ())
-> (LintPassResultConfig -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \LintPassResultConfig
lp_cfg ->
Logger -> LintPassResultConfig -> CoreProgram -> IO ()
lintPassResult Logger
logger LintPassResultConfig
lp_cfg CoreProgram
binds
}
where
mb_flag :: Maybe DumpFlag
mb_flag = case EndPassConfig -> Maybe DumpFlag
ep_dumpFlag EndPassConfig
cfg of
Just DumpFlag
flag | Logger -> DumpFlag -> Bool
logHasDumpFlag Logger
logger DumpFlag
flag -> DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
flag
| Logger -> DumpFlag -> Bool
logHasDumpFlag Logger
logger DumpFlag
Opt_D_verbose_core2core -> DumpFlag -> Maybe DumpFlag
forall a. a -> Maybe a
Just DumpFlag
flag
Maybe DumpFlag
_ -> Maybe DumpFlag
forall a. Maybe a
Nothing
dumpPassResult :: Logger
-> Bool
-> NamePprCtx
-> Maybe DumpFlag
-> String
-> SDoc
-> CoreProgram -> [CoreRule]
-> IO ()
dumpPassResult :: Logger
-> Bool
-> NamePprCtx
-> Maybe DumpFlag
-> String
-> SDoc
-> CoreProgram
-> [CoreRule]
-> IO ()
dumpPassResult Logger
logger Bool
dump_core_sizes NamePprCtx
name_ppr_ctx Maybe DumpFlag
mb_flag String
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
Logger
-> PprStyle -> DumpFlag -> String -> DumpFormat -> SDoc -> IO ()
logDumpFile Logger
logger (NamePprCtx -> PprStyle
mkDumpStyle NamePprCtx
name_ppr_ctx) DumpFlag
flag String
hdr DumpFormat
FormatCore SDoc
dump_doc
; Logger -> JoinArity -> SDoc -> IO ()
Err.debugTraceMsg Logger
logger JoinArity
2 SDoc
size_doc
}
where
size_doc :: SDoc
size_doc = [SDoc] -> SDoc
forall doc. IsLine doc => [doc] -> doc
sep [String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Result size of" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
hdr, JoinArity -> SDoc -> SDoc
nest JoinArity
2 (SDoc
forall doc. IsLine doc => doc
equals SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> CoreStats -> SDoc
forall a. Outputable a => a -> SDoc
ppr (CoreProgram -> CoreStats
coreBindsStats CoreProgram
binds))]
dump_doc :: SDoc
dump_doc = [SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ JoinArity -> SDoc -> SDoc
nest JoinArity
2 SDoc
extra_info
, SDoc
size_doc
, SDoc
blankLine
, if Bool
dump_core_sizes
then CoreProgram -> SDoc
pprCoreBindingsWithSize CoreProgram
binds
else CoreProgram -> SDoc
forall b. OutputableBndr b => [Bind b] -> SDoc
pprCoreBindings CoreProgram
binds
, Bool -> SDoc -> SDoc
forall doc. IsOutput doc => Bool -> doc -> doc
ppUnless ([CoreRule] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CoreRule]
rules) SDoc
pp_rules ]
pp_rules :: SDoc
pp_rules = [SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ SDoc
blankLine
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"------ Local rules for imported ids --------"
, [CoreRule] -> SDoc
pprRules [CoreRule]
rules ]
data LintPassResultConfig = LintPassResultConfig
{ LintPassResultConfig -> DiagOpts
lpr_diagOpts :: !DiagOpts
, LintPassResultConfig -> Platform
lpr_platform :: !Platform
, LintPassResultConfig -> LintFlags
lpr_makeLintFlags :: !LintFlags
, LintPassResultConfig -> Bool
lpr_showLintWarnings :: !Bool
, LintPassResultConfig -> SDoc
lpr_passPpr :: !SDoc
, LintPassResultConfig -> [Var]
lpr_localsInScope :: ![Var]
}
lintPassResult :: Logger -> LintPassResultConfig
-> CoreProgram -> IO ()
lintPassResult :: Logger -> LintPassResultConfig -> CoreProgram -> IO ()
lintPassResult Logger
logger LintPassResultConfig
cfg CoreProgram
binds
= do { let warns_and_errs :: WarnsAndErrs
warns_and_errs = LintConfig -> CoreProgram -> WarnsAndErrs
lintCoreBindings'
(LintConfig
{ l_diagOpts :: DiagOpts
l_diagOpts = LintPassResultConfig -> DiagOpts
lpr_diagOpts LintPassResultConfig
cfg
, l_platform :: Platform
l_platform = LintPassResultConfig -> Platform
lpr_platform LintPassResultConfig
cfg
, l_flags :: LintFlags
l_flags = LintPassResultConfig -> LintFlags
lpr_makeLintFlags LintPassResultConfig
cfg
, l_vars :: [Var]
l_vars = LintPassResultConfig -> [Var]
lpr_localsInScope LintPassResultConfig
cfg
})
CoreProgram
binds
; Logger -> String -> IO ()
Err.showPass Logger
logger (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$
String
"Core Linted result of " String -> String -> String
forall a. [a] -> [a] -> [a]
++
SDocContext -> SDoc -> String
renderWithContext SDocContext
defaultSDocContext (LintPassResultConfig -> SDoc
lpr_passPpr LintPassResultConfig
cfg)
; Logger -> Bool -> SDoc -> SDoc -> WarnsAndErrs -> IO ()
displayLintResults Logger
logger
(LintPassResultConfig -> Bool
lpr_showLintWarnings LintPassResultConfig
cfg) (LintPassResultConfig -> SDoc
lpr_passPpr LintPassResultConfig
cfg)
(CoreProgram -> SDoc
forall b. OutputableBndr b => [Bind b] -> SDoc
pprCoreBindings CoreProgram
binds) WarnsAndErrs
warns_and_errs
}
displayLintResults :: Logger
-> Bool
-> SDoc
-> SDoc
-> WarnsAndErrs
-> IO ()
displayLintResults :: Logger -> Bool -> SDoc -> SDoc -> WarnsAndErrs -> IO ()
displayLintResults Logger
logger Bool
display_warnings SDoc
pp_what SDoc
pp_pgm (Bag SDoc
warns, Bag SDoc
errs)
| Bool -> Bool
not (Bag SDoc -> Bool
forall a. Bag a -> Bool
isEmptyBag Bag SDoc
errs)
= do { Logger -> MessageClass -> SrcSpan -> SDoc -> IO ()
logMsg Logger
logger MessageClass
Err.MCInfo SrcSpan
noSrcSpan
(SDoc -> IO ()) -> SDoc -> IO ()
forall a b. (a -> b) -> a -> b
$ PprStyle -> SDoc -> SDoc
withPprStyle PprStyle
defaultDumpStyle
([SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ String -> SDoc -> SDoc
lint_banner String
"errors" SDoc
pp_what, Bag SDoc -> SDoc
Err.pprMessageBag Bag SDoc
errs
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"*** Offending Program ***"
, SDoc
pp_pgm
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"*** End of Offense ***" ])
; Logger -> JoinArity -> IO ()
Err.ghcExit Logger
logger JoinArity
1 }
| Bool -> Bool
not (Bag SDoc -> Bool
forall a. Bag a -> Bool
isEmptyBag Bag SDoc
warns)
, LogFlags -> Bool
log_enable_debug (Logger -> LogFlags
logFlags Logger
logger)
, Bool
display_warnings
= Logger -> MessageClass -> SrcSpan -> SDoc -> IO ()
logMsg Logger
logger MessageClass
Err.MCInfo 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" SDoc
pp_what SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ Bag SDoc -> SDoc
Err.pprMessageBag ((SDoc -> SDoc) -> Bag SDoc -> Bag SDoc
forall a b. (a -> b) -> Bag a -> Bag b
mapBag (SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ SDoc
blankLine) Bag SDoc
warns))
| Bool
otherwise = () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
lint_banner :: String -> SDoc -> SDoc
lint_banner :: String -> SDoc -> SDoc
lint_banner String
string SDoc
pass = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"*** Core Lint" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
string
SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
": in result of" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc
pass
SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"***"
lintCoreBindings' :: LintConfig -> CoreProgram -> WarnsAndErrs
lintCoreBindings' :: LintConfig -> CoreProgram -> WarnsAndErrs
lintCoreBindings' LintConfig
cfg CoreProgram
binds
= LintConfig -> LintM ((), [UsageEnv]) -> WarnsAndErrs
forall a. LintConfig -> LintM a -> WarnsAndErrs
initL LintConfig
cfg (LintM ((), [UsageEnv]) -> WarnsAndErrs)
-> LintM ((), [UsageEnv]) -> WarnsAndErrs
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 a. [a] -> 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 a. [a] -> 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 a. a -> LintM a
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
([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], [NonEmpty Name]) -> [NonEmpty Name])
-> ([Name], [NonEmpty Name]) -> [NonEmpty Name]
forall a b. (a -> b) -> a -> b
$ (Name -> (Module, OccName)) -> [Name] -> ([Name], [NonEmpty Name])
forall b a. Ord b => (a -> b) -> [a] -> ([a], [NonEmpty a])
removeDupsOn Name -> (Module, OccName)
ord_ext ([Name] -> ([Name], [NonEmpty Name]))
-> [Name] -> ([Name], [NonEmpty Name])
forall a b. (a -> b) -> a -> b
$
(Name -> Bool) -> [Name] -> [Name]
forall a. (a -> Bool) -> [a] -> [a]
filter Name -> Bool
isExternalName ([Name] -> [Name]) -> [Name] -> [Name]
forall a b. (a -> b) -> a -> b
$ (Var -> Name) -> [Var] -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map Var -> Name
Var.varName [Var]
binders
ord_ext :: Name -> (Module, OccName)
ord_ext Name
n = (HasDebugCallStack => Name -> Module
Name -> Module
nameModule Name
n, Name -> OccName
nameOccName Name
n)
lintUnfolding :: Bool
-> LintConfig
-> SrcLoc
-> CoreExpr
-> Maybe (Bag SDoc)
lintUnfolding :: Bool -> LintConfig -> SrcLoc -> CoreExpr -> Maybe (Bag SDoc)
lintUnfolding Bool
is_compulsory LintConfig
cfg SrcLoc
locn CoreExpr
expr
| Bag SDoc -> Bool
forall a. Bag a -> Bool
isEmptyBag Bag SDoc
errs = Maybe (Bag SDoc)
forall a. Maybe a
Nothing
| Bool
otherwise = Bag SDoc -> Maybe (Bag SDoc)
forall a. a -> Maybe a
Just Bag SDoc
errs
where
(Bag SDoc
_warns, Bag SDoc
errs) = LintConfig -> LintM (LintedType, UsageEnv) -> WarnsAndErrs
forall a. LintConfig -> LintM a -> WarnsAndErrs
initL LintConfig
cfg (LintM (LintedType, UsageEnv) -> WarnsAndErrs)
-> LintM (LintedType, UsageEnv) -> WarnsAndErrs
forall a b. (a -> b) -> a -> b
$
if Bool
is_compulsory
then LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintM a -> LintM a
noFixedRuntimeRepChecks 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 :: LintConfig
-> CoreExpr
-> Maybe (Bag SDoc)
lintExpr :: LintConfig -> CoreExpr -> Maybe (Bag SDoc)
lintExpr LintConfig
cfg CoreExpr
expr
| Bag SDoc -> Bool
forall a. Bag a -> Bool
isEmptyBag Bag SDoc
errs = Maybe (Bag SDoc)
forall a. Maybe a
Nothing
| Bool
otherwise = Bag SDoc -> Maybe (Bag SDoc)
forall a. a -> Maybe a
Just Bag SDoc
errs
where
(Bag SDoc
_warns, Bag SDoc
errs) = LintConfig -> LintM (LintedType, UsageEnv) -> WarnsAndErrs
forall a. LintConfig -> LintM a -> WarnsAndErrs
initL LintConfig
cfg 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 { 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 <- thing_inside bndrs'
; return (a, 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 { (rhs_ty, ue) <- Var -> CoreExpr -> LintM (LintedType, UsageEnv)
lintRhs Var
bndr' CoreExpr
rhs
; lintLetBind top_lvl Recursive bndr' rhs rhs_ty
; return ue }
lintLetBody :: LintLocInfo -> [LintedId] -> CoreExpr -> LintM (LintedType, UsageEnv)
lintLetBody :: LintLocInfo -> [Var] -> CoreExpr -> LintM (LintedType, UsageEnv)
lintLetBody LintLocInfo
loc [Var]
bndrs CoreExpr
body
= do { (body_ty, body_ue) <- LintLocInfo
-> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintLocInfo -> LintM a -> LintM a
addLoc LintLocInfo
loc (CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
body)
; mapM_ (lintJoinBndrType body_ty) bndrs
; return (body_ty, 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
forall doc. IsLine doc => String -> doc
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
|| LintedType -> Bool
mightBeLiftedType LintedType
binder_ty
Bool -> Bool -> Bool
|| (RecFlag -> Bool
isNonRec RecFlag
rec_flag Bool -> Bool -> Bool
&& CoreExpr -> Bool
exprOkForSpeculation CoreExpr
rhs)
Bool -> Bool -> Bool
|| Var -> Bool
isDataConWorkId Var
binder Bool -> Bool -> Bool
|| Var -> Bool
isDataConWrapId Var
binder
Bool -> Bool -> Bool
|| CoreExpr -> Bool
exprIsTickedString CoreExpr
rhs)
(Var -> SDoc -> SDoc
badBndrTyMsg Var
binder (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"unlifted"))
; Bool -> SDoc -> LintM ()
checkL (Bool -> Bool
not (TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl Bool -> Bool -> Bool
&& LintedType
binder_ty HasCallStack => LintedType -> LintedType -> Bool
LintedType -> LintedType -> Bool
`eqType` LintedType
addrPrimTy)
Bool -> Bool -> Bool
|| CoreExpr -> Bool
exprIsTickedString CoreExpr
rhs)
(Var -> SDoc
mkTopNonLitStrMsg Var
binder)
; flags <- LintM LintFlags
getLintFlags
; case idJoinPointHood binder of
JoinPointHood
NotJoinPoint -> () -> LintM ()
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
JoinPoint JoinArity
arity -> Bool -> SDoc -> LintM ()
checkL (JoinArity -> LintedType -> Bool
isValidJoinPointType JoinArity
arity LintedType
binder_ty)
(Var -> LintedType -> SDoc
mkInvalidJoinPointMsg Var
binder LintedType
binder_ty)
; when (lf_check_inline_loop_breakers flags
&& isStableUnfolding (realIdUnfolding binder)
&& isStrongLoopBreaker (idOccInfo binder)
&& isInlinePragma (idInlinePragma binder))
(addWarnL (text "INLINE binder is (non-rule) loop breaker:" <+> ppr binder))
; checkL (typeArity (idType binder) >= idArity binder)
(text "idArity" <+> ppr (idArity binder) <+>
text "exceeds typeArity" <+>
ppr (typeArity (idType binder)) <> colon <+>
ppr binder)
; case splitDmdSig (idDmdSig binder) of
([Demand]
demands, Divergence
result_info) | Divergence -> Bool
isDeadEndDiv Divergence
result_info ->
if ([Demand]
demands [Demand] -> JoinArity -> Bool
forall a. [a] -> JoinArity -> Bool
`lengthAtLeast` Var -> JoinArity
idArity Var
binder)
then () -> LintM ()
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
else String -> SDoc -> LintM () -> LintM ()
forall a. String -> SDoc -> a -> a
pprTrace String
"Hack alert: lintLetBind #24623"
(JoinArity -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Var -> JoinArity
idArity Var
binder) SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ DmdSig -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Var -> DmdSig
idDmdSig Var
binder)) (LintM () -> LintM ()) -> LintM () -> LintM ()
forall a b. (a -> b) -> a -> b
$
() -> LintM ()
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
([Demand], Divergence)
_ -> () -> LintM ()
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
; addLoc (RuleOf binder) $ mapM_ (lintCoreRule binder binder_ty) (idCoreRules binder)
; addLoc (UnfoldingOf binder) $
lintIdUnfolding binder binder_ty (idUnfolding binder)
; return () }
lintRhs :: Id -> CoreExpr -> LintM (LintedType, UsageEnv)
lintRhs :: Var -> CoreExpr -> LintM (LintedType, UsageEnv)
lintRhs Var
bndr CoreExpr
rhs
| JoinPoint JoinArity
arity <- Var -> JoinPointHood
idJoinPointHood 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 a b. (a -> b) -> LintM a -> LintM b
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 a b. LintM a -> (a -> LintM b) -> LintM b
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 a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr
Var -> LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
lintLambda
(do fun_ty_ue <- CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
fun
lintCoreArgs fun_ty_ue [Type t, info, 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 { 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
noFixedRuntimeRepChecks (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)
; ensureEqTys bndr_ty ty (mkRhsMsg bndr (text "unfolding") ty) }
lintIdUnfolding Var
_ LintedType
_ Unfolding
_
= () -> LintM ()
forall a. a -> LintM a
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 { co' <- Coercion -> LintM Coercion
lintCoercion Coercion
co
; let (Pair from_ty to_ty, role) = coercionKindRole co'
; checkValueType to_ty $
text "target of cast" <+> quotes (ppr co')
; lintRole co' Representational role
; ensureEqTys from_ty expr_ty (mkCastErr expr co' from_ty expr_ty)
; return to_ty }
lintCoreExpr :: CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr :: CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr (Var Var
var)
= do
var_pair@(var_ty, _) <- Var -> JoinArity -> LintM (LintedType, UsageEnv)
lintIdOcc Var
var JoinArity
0
checkRepPolyBuiltin (Var var) [] var_ty
return var_pair
lintCoreExpr (Lit Literal
lit)
= (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return (Literal -> LintedType
literalType Literal
lit, UsageEnv
zeroUE)
lintCoreExpr (Cast CoreExpr
expr Coercion
co)
= do (expr_ty, ue) <- LintM (LintedType, UsageEnv) -> LintM (LintedType, UsageEnv)
forall a. LintM a -> LintM a
markAllJoinsBad (CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
expr)
to_ty <- lintCastExpr expr expr_ty co
return (to_ty, ue)
lintCoreExpr (Tick CoreTickish
tickish CoreExpr
expr)
= do case CoreTickish
tickish of
Breakpoint XBreakpoint 'TickishPassCore
_ JoinArity
_ [XTickishId 'TickishPassCore]
ids Module
_ -> [Var] -> (Var -> LintM (Var, LintedType)) -> LintM ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Var]
[XTickishId 'TickishPassCore]
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
CoreTickish
_ -> () -> LintM ()
forall a. a -> LintM a
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 (CoreTickish
tickish CoreTickish -> TickishScoping -> Bool
forall (pass :: TickishPass).
GenTickish pass -> TickishScoping -> Bool
`tickishScopesLike` TickishScoping
SoftScope)
lintCoreExpr (Let (NonRec Var
tv (Type LintedType
ty)) CoreExpr
body)
| Var -> Bool
isTyVar Var
tv
=
do { ty' <- LintedType -> LintM LintedType
lintType LintedType
ty
; lintTyBndr tv $ \ 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
BodyOfLet 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 {
(rhs_ty, let_ue) <- Var -> CoreExpr -> LintM (LintedType, UsageEnv)
lintRhs Var
bndr CoreExpr
rhs
; lintBinder LetBind bndr $ \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 (LintLocInfo -> [Var] -> CoreExpr -> LintM (LintedType, UsageEnv)
lintLetBody (Var -> LintLocInfo
BodyOfLet Var
bndr') [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 a. [a] -> 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 a. [a] -> 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
; ((body_type, body_ue), 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' ->
LintLocInfo -> [Var] -> CoreExpr -> LintM (LintedType, UsageEnv)
lintLetBody ([Var] -> LintLocInfo
BodyOfLetRec [Var]
bndrs') [Var]
bndrs' CoreExpr
body
; return (body_type, body_ue `addUE` scaleUE ManyTy (foldr1 addUE 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
ty_arg1 : CoreExpr
ty_arg2 : CoreExpr
arg3 : [CoreExpr]
rest <- [CoreExpr]
args
= do { fun_pair1 <- (LintedType, UsageEnv) -> CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreArg (Var -> LintedType
idType Var
fun, UsageEnv
zeroUE) CoreExpr
ty_arg1
; (fun_ty2, ue2) <- lintCoreArg fun_pair1 ty_arg2
; let lintRunRWCont :: CoreArg -> LintM (LintedType, UsageEnv)
lintRunRWCont expr :: CoreExpr
expr@(Lam Var
_ CoreExpr
_) =
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
; (arg3_ty, ue3) <- lintRunRWCont arg3
; app_ty <- lintValApp arg3 fun_ty2 arg3_ty ue2 ue3
; lintCoreArgs app_ty rest }
| Bool
otherwise
= do { fun_pair <- CoreExpr -> JoinArity -> LintM (LintedType, UsageEnv)
lintCoreFun CoreExpr
fun ([CoreExpr] -> JoinArity
forall a. [a] -> JoinArity
forall (t :: * -> *) a. Foldable t => t a -> JoinArity
length [CoreExpr]
args)
; app_pair@(app_ty, _) <- lintCoreArgs fun_pair args
; checkRepPolyBuiltin fun args app_ty
;
; return app_pair}
where
skipTick :: CoreTickish -> Bool
skipTick CoreTickish
t = case CoreExpr -> CoreExpr
forall b. Expr b -> Expr b
collectFunSimple CoreExpr
e of
(Var Var
v) -> Var -> CoreTickish -> Bool
forall (pass :: TickishPass). Var -> GenTickish pass -> Bool
etaExpansionTick Var
v CoreTickish
t
CoreExpr
_ -> CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable CoreTickish
t
(CoreExpr
fun, [CoreExpr]
args, [CoreTickish]
_source_ticks) = (CoreTickish -> Bool)
-> CoreExpr -> (CoreExpr, [CoreExpr], [CoreTickish])
forall b.
(CoreTickish -> Bool)
-> Expr b -> (Expr b, [Expr b], [CoreTickish])
collectArgsTicks CoreTickish -> Bool
skipTick 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
forall doc. IsLine doc => String -> doc
text String
"Type found as expression" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ty)
lintCoreExpr (Coercion Coercion
co)
= do { 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
; return (coercionType co', 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
forall doc. IsLine doc => String -> doc
text String
"Non term variable" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
var)
; (bndr, linted_bndr_ty) <- Var -> LintM (Var, LintedType)
lookupIdInScope Var
var
; let occ_ty = Var -> LintedType
idType Var
var
bndr_ty = Var -> LintedType
idType Var
bndr
; ensureEqTys occ_ty bndr_ty $
mkBndrOccTypeMismatchMsg bndr var bndr_ty occ_ty
; lf <- getLintFlags
; when (nargs /= 0 && lf_check_static_ptrs lf /= AllowAnywhere) $
checkL (idName var /= makeStaticName) $
text "Found makeStatic nested in an expression"
; checkDeadIdOcc var
; checkJoinOcc var nargs
; case isDataConId_maybe var of
Maybe DataCon
Nothing -> () -> LintM ()
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just DataCon
dc -> String -> DataCon -> LintM ()
checkTypeDataConOcc String
"expression" DataCon
dc
; usage <- varCallSiteUsage var
; return (linted_bndr_ty, 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 { (body_ty, ue) <- LintM (LintedType, UsageEnv)
lintBody
; ue' <- checkLinearity ue var'
; return (mkLamType var' body_ty, ue') }
checkDeadIdOcc :: Id -> LintM ()
checkDeadIdOcc :: Var -> LintM ()
checkDeadIdOcc Var
id
| OccInfo -> Bool
isDeadOcc (Var -> OccInfo
idOccInfo Var
id)
= do { in_case <- LintM Bool
inCasePat
; checkL in_case
(text "Occurrence of a dead Id" <+> ppr id) }
| Bool
otherwise
= () -> LintM ()
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
lintJoinBndrType :: LintedType
-> LintedId
-> LintM ()
lintJoinBndrType :: LintedType -> Var -> LintM ()
lintJoinBndrType LintedType
body_ty Var
bndr
| JoinPoint JoinArity
arity <- Var -> JoinPointHood
idJoinPointHood Var
bndr
, let bndr_ty :: LintedType
bndr_ty = Var -> LintedType
idType Var
bndr
, ([PiTyBinder]
bndrs, LintedType
res) <- LintedType -> ([PiTyBinder], LintedType)
splitPiTys LintedType
bndr_ty
= Bool -> SDoc -> LintM ()
checkL ([PiTyBinder] -> JoinArity
forall a. [a] -> JoinArity
forall (t :: * -> *) a. Foldable t => t a -> JoinArity
length [PiTyBinder]
bndrs JoinArity -> JoinArity -> Bool
forall a. Ord a => a -> a -> Bool
>= JoinArity
arity
Bool -> Bool -> Bool
&& LintedType
body_ty HasCallStack => LintedType -> LintedType -> Bool
LintedType -> LintedType -> Bool
`eqType` [PiTyBinder] -> LintedType -> LintedType
HasDebugCallStack => [PiTyBinder] -> LintedType -> LintedType
mkPiTys (JoinArity -> [PiTyBinder] -> [PiTyBinder]
forall a. JoinArity -> [a] -> [a]
drop JoinArity
arity [PiTyBinder]
bndrs) LintedType
res) (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
SDoc -> JoinArity -> SDoc -> SDoc
hang (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Join point returns different type than body")
JoinArity
2 ([SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Join bndr:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
bndr SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc
dcolon SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Var -> LintedType
idType Var
bndr)
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Join arity:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> JoinArity -> SDoc
forall a. Outputable a => a -> SDoc
ppr JoinArity
arity
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Body type:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
body_ty ])
| Bool
otherwise
= () -> LintM ()
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
checkJoinOcc :: Id -> JoinArity -> LintM ()
checkJoinOcc :: Var -> JoinArity -> LintM ()
checkJoinOcc Var
var JoinArity
n_args
| JoinPoint JoinArity
join_arity_occ <- Var -> JoinPointHood
idJoinPointHood Var
var
= do { mb_join_arity_bndr <- Var -> LintM JoinPointHood
lookupJoinId Var
var
; case mb_join_arity_bndr of {
JoinPointHood
NotJoinPoint -> do { join_set <- LintM IdSet
getValidJoins
; addErrL (text "join set " <+> ppr join_set $$
invalidJoinOcc var) } ;
JoinPoint 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 a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
checkTypeDataConOcc :: String -> DataCon -> LintM ()
checkTypeDataConOcc :: String -> DataCon -> LintM ()
checkTypeDataConOcc String
what DataCon
dc
= Bool -> SDoc -> LintM ()
checkL (Bool -> Bool
not (TyCon -> Bool
isTypeDataTyCon (DataCon -> TyCon
dataConTyCon DataCon
dc))) (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
(String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"type data constructor found in a" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
what SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<> SDoc
forall doc. IsLine doc => doc
colon SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> DataCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr DataCon
dc)
checkRepPolyBuiltin :: CoreExpr
-> [CoreArg]
-> LintedType
-> LintM ()
checkRepPolyBuiltin :: CoreExpr -> [CoreExpr] -> LintedType -> LintM ()
checkRepPolyBuiltin (Var Var
fun_id) [CoreExpr]
args LintedType
app_ty
= do { do_rep_poly_checks <- LintFlags -> Bool
lf_check_fixed_rep (LintFlags -> Bool) -> LintM LintFlags -> LintM Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LintM LintFlags
getLintFlags
; when (do_rep_poly_checks && hasNoBinding fun_id) $
if
| Just dc <- isDataConId_maybe fun_id
, isNewDataCon dc
-> if tcHasFixedRuntimeRep $ dataConTyCon dc
then return ()
else checkRepPolyNewtypeApp dc args app_ty
| otherwise
-> checkRepPolyBuiltinApp fun_id args
}
checkRepPolyBuiltin CoreExpr
_ [CoreExpr]
_ LintedType
_ = () -> LintM ()
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
checkRepPolyNewtypeApp :: DataCon -> [CoreArg] -> LintedType -> LintM ()
checkRepPolyNewtypeApp :: DataCon -> [CoreExpr] -> LintedType -> LintM ()
checkRepPolyNewtypeApp DataCon
nt [CoreExpr]
args LintedType
app_ty
| (CoreExpr -> Bool) -> [CoreExpr] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any CoreExpr -> Bool
forall b. Expr b -> Bool
isValArg [CoreExpr]
args
= () -> LintM ()
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Bool
otherwise
= case LintedType -> [(Scaled LintedType, FunTyFlag)]
getRuntimeArgTys LintedType
app_ty of
(Scaled LintedType
_ LintedType
first_val_arg_ty, FunTyFlag
_):[(Scaled LintedType, FunTyFlag)]
_
| Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ HasDebugCallStack => LintedType -> Bool
LintedType -> Bool
typeHasFixedRuntimeRep LintedType
first_val_arg_ty
-> SDoc -> LintM ()
forall a. SDoc -> LintM a
failWithL (LintedType -> SDoc
err_msg LintedType
first_val_arg_ty)
[(Scaled LintedType, FunTyFlag)]
_ -> () -> LintM ()
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
where
err_msg :: Type -> SDoc
err_msg :: LintedType -> SDoc
err_msg LintedType
bad_arg_ty
= [SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Cannot eta expand unlifted newtype constructor" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc -> SDoc
quotes (DataCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr DataCon
nt) SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<> SDoc
forall doc. IsLine doc => doc
dot
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Its argument type does not have a fixed runtime representation:"
, JoinArity -> SDoc -> SDoc
nest JoinArity
2 (SDoc -> SDoc) -> SDoc -> SDoc
forall a b. (a -> b) -> a -> b
$ LintedType -> SDoc
ppr_ty_ki LintedType
bad_arg_ty ]
ppr_ty_ki :: Type -> SDoc
ppr_ty_ki :: LintedType -> SDoc
ppr_ty_ki LintedType
ty = SDoc
bullet SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ty SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc
dcolon SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr (HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
ty)
checkRepPolyBuiltinApp :: Id -> [CoreArg] -> LintM ()
checkRepPolyBuiltinApp :: Var -> [CoreExpr] -> LintM ()
checkRepPolyBuiltinApp Var
fun_id [CoreExpr]
args = Bool -> SDoc -> LintM ()
checkL ([(SDoc, ConcreteTvOrigin)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(SDoc, ConcreteTvOrigin)]
not_concs) SDoc
err_msg
where
conc_binder_positions :: IntMap ConcreteTvOrigin
conc_binder_positions :: IntMap ConcreteTvOrigin
conc_binder_positions
= Var -> ConcreteTyVars -> IntMap ConcreteTvOrigin
concreteTyVarPositions Var
fun_id
(ConcreteTyVars -> IntMap ConcreteTvOrigin)
-> ConcreteTyVars -> IntMap ConcreteTvOrigin
forall a b. (a -> b) -> a -> b
$ IdDetails -> ConcreteTyVars
idDetailsConcreteTvs
(IdDetails -> ConcreteTyVars) -> IdDetails -> ConcreteTyVars
forall a b. (a -> b) -> a -> b
$ Var -> IdDetails
idDetails Var
fun_id
max_pos :: Int
max_pos :: JoinArity
max_pos =
case IntMap ConcreteTvOrigin -> [JoinArity]
forall a. IntMap a -> [JoinArity]
IntMap.keys IntMap ConcreteTvOrigin
conc_binder_positions of
[] -> JoinArity
0
[JoinArity]
positions -> [JoinArity] -> JoinArity
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [JoinArity]
positions
not_concs :: [(SDoc, ConcreteTvOrigin)]
not_concs :: [(SDoc, ConcreteTvOrigin)]
not_concs =
((JoinArity, Maybe CoreExpr) -> Maybe (SDoc, ConcreteTvOrigin))
-> [(JoinArity, Maybe CoreExpr)] -> [(SDoc, ConcreteTvOrigin)]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (JoinArity, Maybe CoreExpr) -> Maybe (SDoc, ConcreteTvOrigin)
is_bad ([JoinArity] -> [Maybe CoreExpr] -> [(JoinArity, Maybe CoreExpr)]
forall a b. [a] -> [b] -> [(a, b)]
zip [JoinArity
1..JoinArity
max_pos] ((CoreExpr -> Maybe CoreExpr) -> [CoreExpr] -> [Maybe CoreExpr]
forall a b. (a -> b) -> [a] -> [b]
map CoreExpr -> Maybe CoreExpr
forall a. a -> Maybe a
Just [CoreExpr]
args [Maybe CoreExpr] -> [Maybe CoreExpr] -> [Maybe CoreExpr]
forall a. [a] -> [a] -> [a]
++ Maybe CoreExpr -> [Maybe CoreExpr]
forall a. a -> [a]
repeat Maybe CoreExpr
forall a. Maybe a
Nothing))
is_bad :: (Int, Maybe CoreArg) -> Maybe (SDoc, ConcreteTvOrigin)
is_bad :: (JoinArity, Maybe CoreExpr) -> Maybe (SDoc, ConcreteTvOrigin)
is_bad (JoinArity
pos, Maybe CoreExpr
mb_arg)
| Just ConcreteTvOrigin
conc_reason <- JoinArity -> IntMap ConcreteTvOrigin -> Maybe ConcreteTvOrigin
forall a. JoinArity -> IntMap a -> Maybe a
IntMap.lookup JoinArity
pos IntMap ConcreteTvOrigin
conc_binder_positions
, Just SDoc
bad_ty <- case Maybe CoreExpr
mb_arg of
Just (Type LintedType
ki)
| LintedType -> Bool
isConcreteType LintedType
ki
-> Maybe SDoc
forall a. Maybe a
Nothing
| Bool
otherwise
-> SDoc -> Maybe SDoc
forall a. a -> Maybe a
Just (SDoc -> Maybe SDoc) -> SDoc -> Maybe SDoc
forall a b. (a -> b) -> a -> b
$ SDoc -> SDoc
quotes (LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ki) SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"is not concrete."
Just CoreExpr
arg ->
String -> SDoc -> Maybe SDoc
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"checkRepPolyBuiltinApp: expected a type in this position" (SDoc -> Maybe SDoc) -> SDoc -> Maybe SDoc
forall a b. (a -> b) -> a -> b
$
[SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"fun_id:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
fun_id SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc
dcolon SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Var -> LintedType
idType Var
fun_id)
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"pos:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> JoinArity -> SDoc
forall a. Outputable a => a -> SDoc
ppr JoinArity
pos
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"arg:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> CoreExpr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreExpr
arg ]
Maybe CoreExpr
Nothing ->
case ConcreteTvOrigin
conc_reason of
ConcreteFRR FixedRuntimeRepOrigin
frr_orig ->
let ty :: LintedType
ty = FixedRuntimeRepOrigin -> LintedType
frr_type FixedRuntimeRepOrigin
frr_orig
in SDoc -> Maybe SDoc
forall a. a -> Maybe a
Just (SDoc -> Maybe SDoc) -> SDoc -> Maybe SDoc
forall a b. (a -> b) -> a -> b
$ LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ty SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc
dcolon SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr (HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
ty)
= (SDoc, ConcreteTvOrigin) -> Maybe (SDoc, ConcreteTvOrigin)
forall a. a -> Maybe a
Just (SDoc
bad_ty, ConcreteTvOrigin
conc_reason)
| Bool
otherwise
= Maybe (SDoc, ConcreteTvOrigin)
forall a. Maybe a
Nothing
err_msg :: SDoc
err_msg :: SDoc
err_msg
= [SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat ([SDoc] -> SDoc) -> [SDoc] -> SDoc
forall a b. (a -> b) -> a -> b
$ ((SDoc, ConcreteTvOrigin) -> SDoc)
-> [(SDoc, ConcreteTvOrigin)] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map ((SDoc
bullet SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+>) (SDoc -> SDoc)
-> ((SDoc, ConcreteTvOrigin) -> SDoc)
-> (SDoc, ConcreteTvOrigin)
-> SDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SDoc, ConcreteTvOrigin) -> SDoc
ppr_not_conc) [(SDoc, ConcreteTvOrigin)]
not_concs
ppr_not_conc :: (SDoc, ConcreteTvOrigin) -> SDoc
ppr_not_conc :: (SDoc, ConcreteTvOrigin) -> SDoc
ppr_not_conc (SDoc
bad_ty, ConcreteTvOrigin
conc) =
[SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat
[ ConcreteTvOrigin -> SDoc
ppr_conc_orig ConcreteTvOrigin
conc
, JoinArity -> SDoc -> SDoc
nest JoinArity
2 SDoc
bad_ty ]
ppr_conc_orig :: ConcreteTvOrigin -> SDoc
ppr_conc_orig :: ConcreteTvOrigin -> SDoc
ppr_conc_orig (ConcreteFRR FixedRuntimeRepOrigin
frr_orig) =
case FixedRuntimeRepOrigin
frr_orig of
FixedRuntimeRepOrigin { frr_context :: FixedRuntimeRepOrigin -> FixedRuntimeRepContext
frr_context = FixedRuntimeRepContext
ctxt } ->
[SDoc] -> SDoc
forall doc. IsLine doc => [doc] -> doc
hsep [ FixedRuntimeRepContext -> SDoc
forall a. Outputable a => a -> SDoc
ppr FixedRuntimeRepContext
ctxt, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"does not have a fixed runtime representation:" ]
concreteTyVarPositions :: Id -> ConcreteTyVars -> IntMap ConcreteTvOrigin
concreteTyVarPositions :: Var -> ConcreteTyVars -> IntMap ConcreteTvOrigin
concreteTyVarPositions Var
fun_id ConcreteTyVars
conc_tvs
| ConcreteTyVars -> Bool
forall {k} (key :: k) elt. UniqFM key elt -> Bool
isNullUFM ConcreteTyVars
conc_tvs
= IntMap ConcreteTvOrigin
forall a. IntMap a
IntMap.empty
| Bool
otherwise
= case LintedType -> ([Var], LintedType)
splitForAllTyCoVars (Var -> LintedType
idType Var
fun_id) of
([], LintedType
_) -> IntMap ConcreteTvOrigin
forall a. IntMap a
IntMap.empty
([Var]
tvs, LintedType
_) ->
let positions :: IntMap ConcreteTvOrigin
positions =
[(JoinArity, ConcreteTvOrigin)] -> IntMap ConcreteTvOrigin
forall a. [(JoinArity, a)] -> IntMap a
IntMap.fromList
[ (JoinArity
pos, ConcreteTvOrigin
conc_orig)
| (Var
tv, JoinArity
pos) <- [Var] -> [JoinArity] -> [(Var, JoinArity)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Var]
tvs [JoinArity
1..]
, ConcreteTvOrigin
conc_orig <- Maybe ConcreteTvOrigin -> [ConcreteTvOrigin]
forall a. Maybe a -> [a]
maybeToList (Maybe ConcreteTvOrigin -> [ConcreteTvOrigin])
-> Maybe ConcreteTvOrigin -> [ConcreteTvOrigin]
forall a b. (a -> b) -> a -> b
$ ConcreteTyVars -> Name -> Maybe ConcreteTvOrigin
forall a. NameEnv a -> Name -> Maybe a
lookupNameEnv ConcreteTyVars
conc_tvs (Var -> Name
tyVarName Var
tv)
]
in Bool -> SDoc -> IntMap ConcreteTvOrigin -> IntMap ConcreteTvOrigin
forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr (ConcreteTyVars -> JoinArity
forall {k} (key :: k) elt. UniqFM key elt -> JoinArity
sizeUFM ConcreteTyVars
conc_tvs JoinArity -> JoinArity -> Bool
forall a. Eq a => a -> a -> Bool
== IntMap ConcreteTvOrigin -> JoinArity
forall a. IntMap a -> JoinArity
forall (t :: * -> *) a. Foldable t => t a -> JoinArity
length IntMap ConcreteTvOrigin
positions)
([SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"concreteTyVarPositions: missing concreteness information"
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"fun_id:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
fun_id
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"tvs:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> [Var] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Var]
tvs
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Expected # of concrete tvs:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> JoinArity -> SDoc
forall a. Outputable a => a -> SDoc
ppr (ConcreteTyVars -> JoinArity
forall {k} (key :: k) elt. UniqFM key elt -> JoinArity
sizeUFM ConcreteTyVars
conc_tvs)
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
" Actual # of concrete tvs:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> JoinArity -> SDoc
forall a. Outputable a => a -> SDoc
ppr (IntMap ConcreteTvOrigin -> JoinArity
forall a. IntMap a -> JoinArity
forall (t :: * -> *) a. Foldable t => t a -> JoinArity
length IntMap ConcreteTvOrigin
positions) ])
IntMap ConcreteTvOrigin
positions
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
let (Usage
lhs, UsageEnv
body_ue') = UsageEnv -> Var -> (Usage, UsageEnv)
forall n. NamedThing n => UsageEnv -> n -> (Usage, UsageEnv)
popUE UsageEnv
body_ue Var
lam_var
err_msg :: SDoc
err_msg = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Linearity failure in lambda:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
lam_var
SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ Usage -> SDoc
forall a. Outputable a => a -> SDoc
ppr Usage
lhs SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"⊈" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
mult
Usage -> LintedType -> SDoc -> LintM ()
ensureSubUsage Usage
lhs LintedType
mult SDoc
err_msg
UsageEnv -> LintM UsageEnv
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return UsageEnv
body_ue'
Maybe LintedType
Nothing -> UsageEnv -> LintM UsageEnv
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return UsageEnv
body_ue
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
forall doc. IsLine doc => String -> doc
text String
"Unnecessary coercion-to-type injection:"
SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
arg_ty)
; arg_ty' <- LintedType -> LintM LintedType
lintType LintedType
arg_ty
; res <- lintTyApp fun_ty arg_ty'
; return (res, ue) }
lintCoreArg (LintedType
fun_ty, UsageEnv
ue) (Coercion Coercion
co)
= do { 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
; res <- lintCoApp fun_ty co'
; return (res, ue) }
lintCoreArg (LintedType
fun_ty, UsageEnv
fun_ue) CoreExpr
arg
= do { (arg_ty, 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
; flags <- getLintFlags
; when (lf_check_fixed_rep flags) $
do { checkL (typeHasFixedRuntimeRep arg_ty)
(text "Argument does not have a fixed runtime representation"
<+> ppr arg <+> dcolon
<+> parens (ppr arg_ty <+> dcolon <+> ppr (typeKind arg_ty))) }
; lintValApp arg fun_ty arg_ty fun_ue 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 a. a -> LintM a
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 { con_ty' <- LintedType -> LintedType -> LintM LintedType
lintTyApp LintedType
con_ty (Var -> LintedType
mkTyVarTy Var
bndr)
; lintAltBinders rhs_ue case_bndr scrut_ty con_ty' bndrs }
| Bool
otherwise
= do { (con_ty', _) <- 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
; rhs_ue' <- checkCaseLinearity rhs_ue case_bndr var_w bndr
; lintAltBinders rhs_ue' case_bndr scrut_ty con_ty' 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 a. a -> LintM a
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
forall doc. IsLine doc => String -> doc
text String
"Linearity failure in variable:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
bndr
SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ Usage -> SDoc
forall a. Outputable a => a -> SDoc
ppr Usage
lhs SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"⊈" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
rhs
SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Computed by:"
SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"LHS:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc
lhs_formula
SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"RHS:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc
rhs_formula)
lhs_formula :: SDoc
lhs_formula = Usage -> SDoc
forall a. Outputable a => a -> SDoc
ppr Usage
bndr_usage SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"+"
SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc
parens (Usage -> SDoc
forall a. Outputable a => a -> SDoc
ppr Usage
case_bndr_usage SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"*" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> 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
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"*" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> 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)
splitForAllTyVar_maybe LintedType
fun_ty
= do { Var -> LintedType -> LintM ()
lintTyKind Var
tv LintedType
arg_ty
; in_scope <- LintM InScopeSet
getInScope
; return (substTyWithInScope in_scope [tv] [arg_ty] body_ty) }
| Bool
otherwise
= SDoc -> LintM LintedType
forall a. SDoc -> LintM a
failWithL (LintedType -> LintedType -> SDoc
mkTyAppMsg LintedType
fun_ty LintedType
arg_ty)
lintCoApp :: LintedType -> LintedCoercion -> LintM LintedType
lintCoApp :: LintedType -> Coercion -> LintM LintedType
lintCoApp LintedType
fun_ty Coercion
co
| Just (Var
cv,LintedType
body_ty) <- LintedType -> Maybe (Var, LintedType)
splitForAllCoVar_maybe LintedType
fun_ty
, let co_ty :: LintedType
co_ty = Coercion -> LintedType
coercionType Coercion
co
cv_ty :: LintedType
cv_ty = Var -> LintedType
idType Var
cv
, LintedType
cv_ty HasCallStack => LintedType -> LintedType -> Bool
LintedType -> LintedType -> Bool
`eqType` LintedType
co_ty
= do { in_scope <- LintM InScopeSet
getInScope
; let init_subst = InScopeSet -> Subst
mkEmptySubst InScopeSet
in_scope
subst = Subst -> Var -> Coercion -> Subst
extendCvSubst Subst
init_subst Var
cv Coercion
co
; return (substTy subst body_ty) }
| Just (FunTyFlag
_, LintedType
_, LintedType
arg_ty', LintedType
res_ty') <- LintedType -> Maybe (FunTyFlag, LintedType, LintedType, LintedType)
splitFunTy_maybe LintedType
fun_ty
, LintedType
co_ty HasCallStack => LintedType -> LintedType -> Bool
LintedType -> LintedType -> Bool
`eqType` LintedType
arg_ty'
= LintedType -> LintM LintedType
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return (LintedType
res_ty')
| Bool
otherwise
= SDoc -> LintM LintedType
forall a. SDoc -> LintM a
failWithL (LintedType -> Coercion -> SDoc
mkCoAppMsg LintedType
fun_ty Coercion
co)
where
co_ty :: LintedType
co_ty = Coercion -> LintedType
coercionType Coercion
co
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 (FunTyFlag
_, LintedType
w, LintedType
arg_ty', LintedType
res_ty') <- LintedType -> Maybe (FunTyFlag, LintedType, LintedType, LintedType)
splitFunTy_maybe LintedType
fun_ty
= do { LintedType -> LintedType -> SDoc -> LintM ()
ensureEqTys LintedType
arg_ty' LintedType
arg_ty (LintedType -> LintedType -> CoreExpr -> SDoc
mkAppMsg LintedType
arg_ty' LintedType
arg_ty CoreExpr
arg)
; 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 a. a -> LintM a
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
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 HasCallStack => LintedType -> LintedType -> Bool
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
forall doc. IsDoc doc => doc -> doc -> doc
$$ (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Linted Arg kind:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> 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
; (scrut_ty, 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 = Var -> LintedType
varMult Var
var
; alt_ty <- addLoc (CaseTy scrut) $
lintValueType alt_ty
; var_ty <- addLoc (IdTy var) $
lintValueType (idType var)
; let isLitPat (Alt (LitAlt Literal
_) [b]
_ Expr b
_) = Bool
True
isLitPat Alt b
_ = Bool
False
; checkL (not $ isFloatingPrimTy scrut_ty && any isLitPat alts)
(text "Lint warning: Scrutinising floating-point expression with literal pattern in case analysis (see #9238)."
$$ text "scrut" <+> ppr scrut)
; case tyConAppTyCon_maybe (idType var) of
Just TyCon
tycon
| Bool
debugIsOn
, TyCon -> Bool
isAlgTyCon TyCon
tycon
, Bool -> Bool
not (TyCon -> Bool
isAbstractTyCon TyCon
tycon)
, [DataCon] -> Bool
forall a. [a] -> 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
forall doc. IsLine doc => doc -> doc -> doc
<+> 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 a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Maybe TyCon
_otherwise -> () -> LintM ()
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
; subst <- getSubst
; ensureEqTys var_ty scrut_ty (mkScrutMsg var var_ty scrut_ty subst)
; lintBinder CaseBind var $ \Var
_ ->
do {
; 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)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [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 = (LintedType -> UsageEnv -> UsageEnv
scaleUE LintedType
scrut_mult UsageEnv
scrut_ue) UsageEnv -> UsageEnv -> UsageEnv
`addUE` [UsageEnv] -> UsageEnv
supUEs [UsageEnv]
alt_ues
; checkCaseAlts e scrut_ty alts
; return (alt_ty, 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}. Alt b -> Bool
non_deflt [Alt Var]
con_alts) (CoreExpr -> SDoc
mkNonDefltMsg CoreExpr
e)
; Bool -> SDoc -> LintM ()
checkL ([Alt Var] -> Bool
forall {a}. [Alt a] -> 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 a. [a] -> 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 b. [Alt b] -> ([Alt b], Maybe (Expr b))
findDefault [Alt Var]
alts
increasing_tag :: [Alt a] -> Bool
increasing_tag (Alt a
alt1 : rest :: [Alt a]
rest@( Alt a
alt2 : [Alt a]
_)) = Alt a
alt1 Alt a -> Alt a -> Bool
forall a. Alt a -> Alt a -> Bool
`ltAlt` Alt a
alt2 Bool -> Bool -> Bool
&& [Alt a] -> Bool
increasing_tag [Alt a]
rest
increasing_tag [Alt a]
_ = Bool
True
non_deflt :: Alt b -> Bool
non_deflt (Alt AltCon
DEFAULT [b]
_ Expr b
_) = Bool
False
non_deflt Alt b
_ = 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 { (actual_ty, ue) <- CoreExpr -> LintM (LintedType, UsageEnv)
lintCoreExpr CoreExpr
expr
; ensureEqTys actual_ty ann_ty (mkCaseAltMsg expr actual_ty ann_ty)
; return ue }
lintCoreAlt :: Var
-> LintedType
-> Mult
-> LintedType
-> CoreAlt
-> LintM UsageEnv
lintCoreAlt :: Var
-> LintedType
-> LintedType
-> LintedType
-> Alt Var
-> LintM UsageEnv
lintCoreAlt Var
case_bndr LintedType
_ LintedType
scrut_mult LintedType
alt_ty (Alt AltCon
DEFAULT [Var]
args CoreExpr
rhs) =
do { Bool -> SDoc -> LintM ()
lintL ([Var] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Var]
args) ([Var] -> SDoc
mkDefaultArgsMsg [Var]
args)
; rhs_ue <- CoreExpr -> LintedType -> LintM UsageEnv
lintAltExpr CoreExpr
rhs LintedType
alt_ty
; let (case_bndr_usage, rhs_ue') = popUE rhs_ue case_bndr
err_msg = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Linearity failure in the DEFAULT clause:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
case_bndr
SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ Usage -> SDoc
forall a. Outputable a => a -> SDoc
ppr Usage
case_bndr_usage SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"⊈" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
scrut_mult
; ensureSubUsage case_bndr_usage scrut_mult err_msg
; return rhs_ue' }
lintCoreAlt Var
case_bndr LintedType
scrut_ty LintedType
_ LintedType
alt_ty (Alt (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 a. [a] -> 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)
; rhs_ue <- CoreExpr -> LintedType -> LintM UsageEnv
lintAltExpr CoreExpr
rhs LintedType
alt_ty
; return (deleteUE rhs_ue case_bndr)
}
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@(Alt (DataAlt DataCon
con) [Var]
args CoreExpr
rhs)
| TyCon -> Bool
isNewTyCon (DataCon -> TyCon
dataConTyCon DataCon
con)
= UsageEnv
zeroUE UsageEnv -> LintM () -> LintM UsageEnv
forall a b. a -> LintM b -> LintM a
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
{ String -> DataCon -> LintM ()
checkTypeDataConOcc String
"pattern" DataCon
con
; 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
; binderMult :: PiTyBinder -> LintedType
binderMult (Named ForAllTyBinder
_) = LintedType
ManyTy
; binderMult (Anon Scaled LintedType
st FunTyFlag
_) = Scaled LintedType -> LintedType
forall a. Scaled a -> LintedType
scaledMult Scaled LintedType
st
; multiplicities :: [LintedType]
multiplicities = (PiTyBinder -> LintedType) -> [PiTyBinder] -> [LintedType]
forall a b. (a -> b) -> [a] -> [b]
map PiTyBinder -> LintedType
binderMult ([PiTyBinder] -> [LintedType]) -> [PiTyBinder] -> [LintedType]
forall a b. (a -> b) -> a -> b
$ ([PiTyBinder], LintedType) -> [PiTyBinder]
forall a b. (a, b) -> a
fst (([PiTyBinder], LintedType) -> [PiTyBinder])
-> ([PiTyBinder], LintedType) -> [PiTyBinder]
forall a b. (a -> b) -> a -> b
$ LintedType -> ([PiTyBinder], LintedType)
splitPiTys LintedType
con_payload_ty }
; 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
{
rhs_ue <- CoreExpr -> LintedType -> LintM UsageEnv
lintAltExpr CoreExpr
rhs LintedType
alt_ty
; rhs_ue' <- addLoc (CasePat alt) (lintAltBinders rhs_ue case_bndr scrut_ty con_payload_ty (zipEqual "lintCoreAlt" multiplicities args'))
; return $ deleteUE rhs_ue' case_bndr
}
}
| Bool
otherwise
= UsageEnv
zeroUE UsageEnv -> LintM () -> LintM UsageEnv
forall a b. a -> LintM b -> LintM a
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
forall doc. IsLine doc => String -> doc
text String
"Multiplicity of variable does not agree with its context"
SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ SDoc
doc
SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
actual_usage
SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Annotation:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> 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 { subst <- LintM Subst
getSubst
; tcv_type' <- lintType (varType tcv)
; let tcv' = InScopeSet -> Var -> Var
uniqAway (Subst -> InScopeSet
getSubstInScope Subst
subst) (Var -> Var) -> Var -> Var
forall a b. (a -> b) -> a -> b
$
Var -> LintedType -> Var
setVarType Var
tcv LintedType
tcv_type'
subst' = Subst -> Var -> Var -> Subst
extendTCvSubstWithClone Subst
subst Var
tcv Var
tcv'
; if (isTyVar tcv)
then
lintL (isLiftedTypeKind (typeKind tcv_type')) $
hang (text "TyVar whose kind does not have kind Type:")
2 (ppr tcv' <+> dcolon <+> ppr tcv_type' <+> dcolon <+> ppr (typeKind tcv_type'))
else
lintL (isCoVarType tcv_type') $
text "CoVar with non-coercion type:" <+> pprTyVar tcv
; updateSubst subst' (thing_inside 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
= Bool -> SDoc -> LintM a -> LintM a
forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr (Var -> Bool
isId Var
id) (Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
id) (LintM a -> LintM a) -> LintM a -> LintM a
forall a b. (a -> b) -> a -> b
$
do { flags <- LintM LintFlags
getLintFlags
; checkL (not (lf_check_global_ids flags) || isLocalId id)
(text "Non-local Id binder" <+> ppr id)
; checkL (not (isExportedId id) || is_top_lvl)
(mkNonTopExportedMsg id)
; checkL (not (isExternalName (Var.varName id)) || is_top_lvl)
(mkNonTopExternalNameMsg id)
; lintL (isJoinId id || not (lf_check_fixed_rep flags)
|| typeHasFixedRuntimeRep id_ty) $
text "Binder does not have a fixed runtime representation:" <+> ppr id <+> dcolon <+>
parens (ppr id_ty <+> dcolon <+> ppr (typeKind id_ty))
; when (isJoinId id) $
checkL (not is_top_lvl && is_let_bind) $
mkBadJoinBindMsg id
; lintL (not (isCoVarType id_ty))
(text "Non-CoVar has coercion type" <+> ppr id <+> dcolon <+> ppr id_ty)
; lintL (not (bind_site == LambdaBind && isEvaldUnfolding (idUnfolding id)))
(text "Lambda binder with value or OtherCon unfolding.")
; linted_ty <- addLoc (IdTy id) (lintValueType id_ty)
; addInScopeId id linted_ty $
thing_inside (setIdType id 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 { ty' <- LintedType -> LintM LintedType
lintType LintedType
ty
; let sk = HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
ty'
; lintL (isTYPEorCONSTRAINT sk) $
hang (text "Ill-kinded type:" <+> ppr ty)
2 (text "has kind:" <+> ppr sk)
; return ty' }
checkTyCon :: TyCon -> LintM ()
checkTyCon :: TyCon -> LintM ()
checkTyCon TyCon
tc
= Bool -> SDoc -> LintM ()
checkL (Bool -> Bool
not (TyCon -> Bool
isTcTyCon TyCon
tc)) (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Found TcTyCon:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> TyCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyCon
tc)
checkTyCoVarInScope :: Subst -> TyCoVar -> LintM ()
checkTyCoVarInScope :: Subst -> Var -> LintM ()
checkTyCoVarInScope Subst
subst Var
tcv
= Bool -> SDoc -> LintM ()
checkL (Var
tcv Var -> Subst -> Bool
`isInScope` Subst
subst) (SDoc -> LintM ()) -> SDoc -> LintM ()
forall a b. (a -> b) -> a -> b
$
SDoc -> JoinArity -> SDoc -> SDoc
hang (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"The type or coercion variable" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> BindingSite -> Var -> SDoc
forall a. OutputableBndr a => BindingSite -> a -> SDoc
pprBndr BindingSite
LetBind Var
tcv)
JoinArity
2 (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"is out of scope")
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 { subst <- LintM Subst
getSubst
; case lookupTyVar subst tv of
Just LintedType
linted_ty -> LintedType -> LintM LintedType
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return LintedType
linted_ty
Maybe LintedType
Nothing -> do { Subst -> Var -> LintM ()
checkTyCoVarInScope Subst
subst Var
tv
; LintedType -> LintM LintedType
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return (Var -> LintedType
TyVarTy Var
tv) }
}
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
forall doc. IsLine doc => String -> doc
text String
"TyConApp to the left of AppTy:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ty
| Bool
otherwise
= do { t1' <- LintedType -> LintM LintedType
lintType LintedType
t1
; t2' <- lintType t2
; lint_ty_app ty (typeKind t1') [t2']
; return (AppTy t1' t2') }
lintType ty :: LintedType
ty@(TyConApp TyCon
tc [LintedType]
tys)
| TyCon -> Bool
isTypeSynonymTyCon TyCon
tc Bool -> Bool -> Bool
|| TyCon -> Bool
isTypeFamilyTyCon TyCon
tc
= do { 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
; lintTySynFamApp report_unsat ty tc tys }
| Just {} <- HasDebugCallStack => TyCon -> [LintedType] -> Maybe LintedType
TyCon -> [LintedType] -> Maybe LintedType
tyConAppFunTy_maybe TyCon
tc [LintedType]
tys
= SDoc -> LintM LintedType
forall a. SDoc -> LintM a
failWithL (SDoc -> JoinArity -> SDoc -> SDoc
hang (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Saturated application of" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc -> SDoc
quotes (TyCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyCon
tc)) JoinArity
2 (LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ty))
| Bool
otherwise
= do { TyCon -> LintM ()
checkTyCon TyCon
tc
; tys' <- (LintedType -> LintM LintedType)
-> [LintedType] -> LintM [LintedType]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM LintedType -> LintM LintedType
lintType [LintedType]
tys
; lint_ty_app ty (tyConKind tc) tys'
; return (TyConApp tc tys') }
lintType ty :: LintedType
ty@(FunTy FunTyFlag
af LintedType
tw LintedType
t1 LintedType
t2)
= do { t1' <- LintedType -> LintM LintedType
lintType LintedType
t1
; t2' <- lintType t2
; tw' <- lintType tw
; lintArrow (text "type or kind" <+> quotes (ppr ty)) t1' t2' tw'
; let real_af = HasDebugCallStack => LintedType -> LintedType -> FunTyFlag
LintedType -> LintedType -> FunTyFlag
chooseFunTyFlag LintedType
t1 LintedType
t2
; unless (real_af == af) $ addErrL $
hang (text "Bad FunTyFlag in FunTy")
2 (vcat [ ppr ty
, text "FunTyFlag =" <+> ppr af
, text "Computed FunTyFlag =" <+> ppr real_af ])
; return (FunTy af tw' t1' t2') }
lintType ty :: LintedType
ty@(ForAllTy (Bndr Var
tcv ForAllTyFlag
vis) LintedType
body_ty)
| Bool -> Bool
not (Var -> Bool
isTyCoVar Var
tcv)
= SDoc -> LintM LintedType
forall a. SDoc -> LintM a
failWithL (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Non-Tyvar or Non-Covar bound in type:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> 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 { body_ty' <- LintedType -> LintM LintedType
lintType LintedType
body_ty
; lintForAllBody tcv' body_ty'
; when (isCoVar tcv) $
lintL (tcv `elemVarSet` tyCoVarsOfType body_ty) $
text "Covar does not occur in the body:" <+> (ppr tcv $$ ppr body_ty)
; return (ForAllTy (Bndr tcv' vis) body_ty') }
lintType ty :: LintedType
ty@(LitTy TyLit
l)
= do { TyLit -> LintM ()
lintTyLit TyLit
l; LintedType -> LintM LintedType
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return LintedType
ty }
lintType (CastTy LintedType
ty Coercion
co)
= do { ty' <- LintedType -> LintM LintedType
lintType LintedType
ty
; co' <- lintStarCoercion co
; let tyk = HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
ty'
cok = Coercion -> LintedType
coercionLKind Coercion
co'
; ensureEqTys tyk cok (mkCastTyErr ty co tyk cok)
; return (CastTy ty' co') }
lintType (CoercionTy Coercion
co)
= do { co' <- Coercion -> LintM Coercion
lintCoercion Coercion
co
; return (CoercionTy 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
forall doc. IsLine doc => String -> doc
text String
"the body of forall:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> 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 a. a -> LintM a
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
forall doc. IsLine doc => String -> doc
text String
"Variable escape in forall:")
JoinArity
2 ([SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"tyvar:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
tcv
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"type:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
body_ty
, String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"kind:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> 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
forall doc. IsLine doc => String -> doc
text String
"Un-saturated type application") JoinArity
2 (LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ty))
| ExpandsSyn [(Var, LintedType)]
tenv LintedType
rhs [LintedType]
tys' <- TyCon -> [LintedType] -> ExpandSynResult LintedType
forall tyco. TyCon -> [tyco] -> ExpandSynResult tyco
expandSynTyCon_maybe TyCon
tc [LintedType]
tys
, let expanded_ty :: LintedType
expanded_ty = LintedType -> [LintedType] -> LintedType
mkAppTys (HasDebugCallStack => Subst -> LintedType -> LintedType
Subst -> LintedType -> LintedType
substTy ([(Var, LintedType)] -> Subst
mkTvSubstPrs [(Var, LintedType)]
tenv) LintedType
rhs) [LintedType]
tys'
= do {
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)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM LintedType -> LintM LintedType
lintType [LintedType]
tys)
; when report_unsat $
do { _ <- lintType expanded_ty
; return () }
; lint_ty_app ty (tyConKind tc) tys'
; return (TyConApp tc tys') }
| Bool
otherwise
= do { tys' <- (LintedType -> LintM LintedType)
-> [LintedType] -> LintM [LintedType]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM LintedType -> LintM LintedType
lintType [LintedType]
tys
; lint_ty_app ty (tyConKind tc) tys'
; return (TyConApp tc tys') }
checkValueType :: LintedType -> SDoc -> LintM ()
checkValueType :: LintedType -> SDoc -> LintM ()
checkValueType LintedType
ty SDoc
doc
= Bool -> SDoc -> LintM ()
lintL (LintedType -> Bool
isTYPEorCONSTRAINT LintedType
kind)
(String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Non-Type-like kind when Type-like expected:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
kind SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"when checking" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> 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
isTYPEorCONSTRAINT LintedType
k1) (SDoc -> LintedType -> LintM ()
report (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"argument") LintedType
k1)
; Bool -> LintM () -> LintM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (LintedType -> Bool
isTYPEorCONSTRAINT LintedType
k2) (SDoc -> LintedType -> LintM ()
report (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"result") LintedType
k2)
; Bool -> LintM () -> LintM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (LintedType -> Bool
isMultiplicityTy LintedType
kw) (SDoc -> LintedType -> LintM ()
report (String -> SDoc
forall doc. IsLine doc => String -> doc
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
report :: SDoc -> LintedType -> LintM ()
report SDoc
ar LintedType
k = SDoc -> LintM ()
addErrL ([SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ SDoc -> JoinArity -> SDoc -> SDoc
hang (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Ill-kinded" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc
ar)
JoinArity
2 (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"in" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc
what)
, SDoc
what SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"kind:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
k ])
lint_ty_app :: Type -> LintedKind -> [LintedType] -> LintM ()
lint_ty_app :: LintedType -> LintedType -> [LintedType] -> LintM ()
lint_ty_app LintedType
msg_ty LintedType
k [LintedType]
tys
= (LintedType -> SDoc)
-> LintedType -> LintedType -> [LintedType] -> LintM ()
forall msg_thing.
Outputable msg_thing =>
(msg_thing -> SDoc)
-> msg_thing -> LintedType -> [LintedType] -> LintM ()
lint_app (\LintedType
msg_ty -> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"type" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc -> SDoc
quotes (LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
msg_ty)) LintedType
msg_ty LintedType
k [LintedType]
tys
lint_co_app :: Coercion -> LintedKind -> [LintedType] -> LintM ()
lint_co_app :: Coercion -> LintedType -> [LintedType] -> LintM ()
lint_co_app Coercion
msg_ty LintedType
k [LintedType]
tys
= (Coercion -> SDoc)
-> Coercion -> LintedType -> [LintedType] -> LintM ()
forall msg_thing.
Outputable msg_thing =>
(msg_thing -> SDoc)
-> msg_thing -> LintedType -> [LintedType] -> LintM ()
lint_app (\Coercion
msg_ty -> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"coercion" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc -> SDoc
quotes (Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
msg_ty)) Coercion
msg_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 a. a -> LintM a
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
forall doc. IsLine doc => String -> doc
text String
"Negative type literal:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Integer -> SDoc
forall doc. IsLine doc => Integer -> doc
integer Integer
n
lintTyLit (StrTyLit FastString
_) = () -> LintM ()
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
lintTyLit (CharTyLit Char
_) = () -> LintM ()
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
lint_app :: Outputable msg_thing => (msg_thing -> SDoc) -> msg_thing -> LintedKind -> [LintedType] -> LintM ()
lint_app :: forall msg_thing.
Outputable msg_thing =>
(msg_thing -> SDoc)
-> msg_thing -> LintedType -> [LintedType] -> LintM ()
lint_app msg_thing -> SDoc
mk_msg msg_thing
msg_type !LintedType
kfn [LintedType]
arg_tys
= do { !in_scope <- LintM InScopeSet
getInScope
; go_app in_scope kfn arg_tys
}
where
go_app :: InScopeSet -> LintedKind -> [Type] -> LintM ()
go_app :: InScopeSet -> LintedType -> [LintedType] -> LintM ()
go_app !InScopeSet
in_scope !LintedType
kfn [LintedType]
ta
| Just LintedType
kfn' <- LintedType -> Maybe LintedType
coreView LintedType
kfn
= InScopeSet -> LintedType -> [LintedType] -> LintM ()
go_app InScopeSet
in_scope LintedType
kfn' [LintedType]
ta
go_app InScopeSet
_in_scope LintedType
_kind [] = () -> LintM ()
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
go_app InScopeSet
in_scope fun_kind :: LintedType
fun_kind@(FunTy FunTyFlag
_ LintedType
_ LintedType
kfa LintedType
kfb) (LintedType
ta:[LintedType]
tas)
= 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 HasCallStack => LintedType -> LintedType -> Bool
LintedType -> LintedType -> Bool
`eqType` LintedType
kfa) (LintM () -> LintM ()) -> LintM () -> LintM ()
forall a b. (a -> b) -> a -> b
$
SDoc -> LintM ()
addErrL (LintedType
-> [LintedType] -> (msg_thing -> SDoc) -> msg_thing -> SDoc -> SDoc
forall a1 a2 t.
(Outputable a1, Outputable a2) =>
a1 -> a2 -> (t -> SDoc) -> t -> SDoc -> SDoc
lint_app_fail_msg LintedType
kfn [LintedType]
arg_tys msg_thing -> SDoc
mk_msg msg_thing
msg_type (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Fun:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> (LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
fun_kind SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ta SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc
dcolon SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ka)))
; InScopeSet -> LintedType -> [LintedType] -> LintM ()
go_app InScopeSet
in_scope LintedType
kfb [LintedType]
tas }
go_app InScopeSet
in_scope (ForAllTy (Bndr Var
kv ForAllTyFlag
_vis) LintedType
kfn) (LintedType
ta:[LintedType]
tas)
= 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 HasCallStack => LintedType -> LintedType -> Bool
LintedType -> LintedType -> Bool
`eqType` LintedType
kv_kind) (LintM () -> LintM ()) -> LintM () -> LintM ()
forall a b. (a -> b) -> a -> b
$
SDoc -> LintM ()
addErrL (LintedType
-> [LintedType] -> (msg_thing -> SDoc) -> msg_thing -> SDoc -> SDoc
forall a1 a2 t.
(Outputable a1, Outputable a2) =>
a1 -> a2 -> (t -> SDoc) -> t -> SDoc -> SDoc
lint_app_fail_msg LintedType
kfn [LintedType]
arg_tys msg_thing -> SDoc
mk_msg msg_thing
msg_type (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Forall:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> (Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
kv SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
kv_kind SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$
LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ta SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc
dcolon SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
ka)))
; let kind' :: LintedType
kind' = HasDebugCallStack => Subst -> LintedType -> LintedType
Subst -> LintedType -> LintedType
substTy (Subst -> Var -> LintedType -> Subst
extendTCvSubst (InScopeSet -> Subst
mkEmptySubst InScopeSet
in_scope) Var
kv LintedType
ta) LintedType
kfn
; InScopeSet -> LintedType -> [LintedType] -> LintM ()
go_app InScopeSet
in_scope LintedType
kind' [LintedType]
tas }
go_app InScopeSet
_ LintedType
kfn [LintedType]
ta
= SDoc -> LintM ()
forall a. SDoc -> LintM a
failWithL (LintedType
-> [LintedType] -> (msg_thing -> SDoc) -> msg_thing -> SDoc -> SDoc
forall a1 a2 t.
(Outputable a1, Outputable a2) =>
a1 -> a2 -> (t -> SDoc) -> t -> SDoc -> SDoc
lint_app_fail_msg LintedType
kfn [LintedType]
arg_tys msg_thing -> SDoc
mk_msg msg_thing
msg_type (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Not a fun:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> (LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr LintedType
kfn SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ [LintedType] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [LintedType]
ta)))
lint_app_fail_msg :: (Outputable a1, Outputable a2) => a1 -> a2 -> (t -> SDoc) -> t -> SDoc -> SDoc
lint_app_fail_msg :: forall a1 a2 t.
(Outputable a1, Outputable a2) =>
a1 -> a2 -> (t -> SDoc) -> t -> SDoc -> SDoc
lint_app_fail_msg a1
kfn a2
arg_tys t -> SDoc
mk_msg t
msg_type SDoc
extra = [SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ SDoc -> JoinArity -> SDoc -> SDoc
hang (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Kind application error in") JoinArity
2 (t -> SDoc
mk_msg t
msg_type)
, JoinArity -> SDoc -> SDoc
nest JoinArity
2 (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Function kind =" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> a1 -> SDoc
forall a. Outputable a => a -> SDoc
ppr a1
kfn)
, JoinArity -> SDoc -> SDoc
nest JoinArity
2 (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Arg types =" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> a2 -> SDoc
forall a. Outputable a => a -> SDoc
ppr a2
arg_tys)
, SDoc
extra ]
lintCoreRule :: OutVar -> LintedType -> CoreRule -> LintM ()
lintCoreRule :: Var -> LintedType -> CoreRule -> LintM ()
lintCoreRule Var
_ LintedType
_ (BuiltinRule {})
= () -> LintM ()
forall a. a -> LintM a
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 { (lhs_ty, _) <- (LintedType, UsageEnv)
-> [CoreExpr] -> LintM (LintedType, UsageEnv)
lintCoreArgs (LintedType
fun_ty, UsageEnv
zeroUE) [CoreExpr]
args
; (rhs_ty, _) <- case idJoinPointHood fun of
JoinPoint 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 }
JoinPointHood
_ -> 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
; ensureEqTys lhs_ty rhs_ty $
(rule_doc <+> vcat [ text "lhs type:" <+> ppr lhs_ty
, text "rhs type:" <+> ppr rhs_ty
, text "fun_ty:" <+> ppr fun_ty ])
; let bad_bndrs = (Var -> Bool) -> [Var] -> [Var]
forall a. (a -> Bool) -> [a] -> [a]
filter Var -> Bool
is_bad_bndr [Var]
bndrs
; checkL (null bad_bndrs)
(rule_doc <+> text "unbound" <+> ppr bad_bndrs)
}
where
rule_doc :: SDoc
rule_doc = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Rule" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc
doubleQuotes (FastString -> SDoc
forall doc. IsLine doc => FastString -> doc
ftext FastString
name) SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<> SDoc
forall doc. IsLine doc => doc
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 { g' <- Coercion -> LintM Coercion
lintCoercion Coercion
g
; let Pair t1 t2 = coercionKind g'
; checkValueType t1 (text "the kind of the left type in" <+> ppr g)
; checkValueType t2 (text "the kind of the right type in" <+> ppr g)
; lintRole g Nominal (coercionRole g)
; return 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
forall doc. IsLine doc => String -> doc
text String
"Bad CoVarCo:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Var -> SDoc
forall a. Outputable a => a -> SDoc
ppr Var
cv)
JoinArity
2 (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"With offending type:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> LintedType -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Var -> LintedType
varType Var
cv)))
| Bool
otherwise
= do { subst <- LintM Subst
getSubst
; case lookupCoVar subst cv of
Just Coercion
linted_co -> Coercion -> LintM Coercion
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return Coercion
linted_co ;
Maybe Coercion
Nothing -> do { Subst -> Var -> LintM ()
checkTyCoVarInScope Subst
subst Var
cv
; Coercion -> LintM Coercion
forall a. a -> LintM a
forall (m :: * -> *) a. Monad m => a -> m a
return (Var -> Coercion
CoVarCo Var
cv) }
}
lintCoercion (Refl LintedType
ty)
= do { ty' <- LintedType -> LintM LintedType
lintType LintedType
ty
; return (Refl ty') }
lintCoercion (GRefl Role
r LintedType
ty MCoercion
MRefl)
= do { ty' <- LintedType -> LintM LintedType
lintType LintedType
ty
; return (GRefl r ty' MRefl) }
lintCoercion (GRefl Role
r LintedType
ty (MCo Coercion
co))
= do { ty' <- LintedType -> LintM LintedType
lintType LintedType
ty
; co' <- lintCoercion co
; let tk = HasDebugCallStack => LintedType -> LintedType
LintedType -> LintedType
typeKind LintedType
ty'
tl = Coercion -> LintedType
coercionLKind Coercion
co'
; ensureEqTys tk tl $
hang (text "GRefl coercion kind mis-match:" <+> ppr co)
2 (vcat [ppr ty', ppr tk, ppr tl])
; lintRole co' Nominal (coercionRole co')
; return (GRefl r ty' (MCo co')) }
lintCoercion co :: Coercion
co@(TyConAppCo Role
r TyCon
tc [Coercion]
cos)
| Just {} <- HasDebugCallStack => Role -> TyCon -> [Coercion] -> Maybe Coercion
Role -> TyCon -> [Coercion] -> Maybe Coercion
tyConAppFunCo_maybe Role
r TyCon
tc [Coercion]
cos
= SDoc -> LintM Coercion
forall a. SDoc -> LintM a
failWithL (SDoc -> JoinArity -> SDoc -> SDoc
hang (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Saturated application of" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> SDoc -> SDoc
quotes (TyCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr TyCon
tc))
JoinArity
2 (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
forall doc. IsLine doc => String -> doc
text String
"Synonym in TyConAppCo:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co)
| Bool
otherwise
= do { TyCon -> LintM ()
checkTyCon TyCon
tc
; cos' <- (Coercion -> LintM Coercion) -> [Coercion] -> LintM [Coercion]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM Coercion -> LintM Coercion
lintCoercion [Coercion]
cos
; let (co_kinds, co_roles) = unzip (map coercionKindRole cos')
; lint_co_app co (tyConKind tc) (map pFst co_kinds)
; lint_co_app co (tyConKind tc) (map pSnd co_kinds)
; zipWithM_ (lintRole co) (tyConRoleListX r tc) co_roles
; return (TyConAppCo r tc cos') }
lintCoercion co :: Coercion
co@(AppCo Coercion
co1 Coercion
co2)
| TyConAppCo {} <- Coercion
co1
= SDoc -> LintM Coercion
forall a. SDoc -> LintM a
failWithL (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"TyConAppCo to the left of AppCo:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> 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
forall doc. IsLine doc => String -> doc
text String
"Refl (TyConApp ...) to the left of AppCo:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co)
| Bool
otherwise
= do { co1' <- Coercion -> LintM Coercion
lintCoercion Coercion
co1
; co2' <- lintCoercion co2
; let (Pair lk1 rk1, r1) = coercionKindRole co1'
(Pair lk2 rk2, r2) = coercionKindRole co2'
; lint_co_app co (typeKind lk1) [lk2]
; lint_co_app co (typeKind rk1) [rk2]
; if r1 == Phantom
then lintL (r2 == Phantom || r2 == Nominal)
(text "Second argument in AppCo cannot be R:" $$
ppr co)
else lintRole co Nominal r2
; return (AppCo co1' co2') }
lintCoercion co :: Coercion
co@(ForAllCo { fco_tcv :: Coercion -> Var
fco_tcv = Var
tcv, fco_visL :: Coercion -> ForAllTyFlag
fco_visL = ForAllTyFlag
visL, fco_visR :: Coercion -> ForAllTyFlag
fco_visR = ForAllTyFlag
visR
, fco_kind :: Coercion -> Coercion
fco_kind = Coercion
kind_co, fco_body :: Coercion -> Coercion
fco_body = Coercion
body_co })
| Bool -> Bool
not (Var -> Bool
isTyCoVar Var
tcv)
= SDoc -> LintM Coercion
forall a. SDoc -> LintM a
failWithL (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Non tyco binder in ForAllCo:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co)
| Bool
otherwise
= do { kind_co' <- Coercion -> LintM Coercion
lintStarCoercion Coercion
kind_co
; lintTyCoBndr tcv $ \Var
tcv' ->
do { body_co' <- Coercion -> LintM Coercion
lintCoercion Coercion
body_co
; ensureEqTys (varType tcv') (coercionLKind kind_co') $
text "Kind mis-match in ForallCo" <+> ppr co