summaryrefslogtreecommitdiff
path: root/compiler/coreSyn
diff options
context:
space:
mode:
authorRyan Scott <ryan.gl.scott@gmail.com>2017-06-02 13:12:11 -0400
committerBen Gamari <ben@smart-cactus.org>2017-06-02 13:12:13 -0400
commita786b136f48dfcf907dad55bcdbc4fcd247f2794 (patch)
tree9c6abee43aa398fdd8168b1cb7bd2d3fb5e6bacf /compiler/coreSyn
parent811a2986475d88f73bb22b4600970039e1b582d6 (diff)
downloadhaskell-a786b136f48dfcf907dad55bcdbc4fcd247f2794.tar.gz
Use lengthIs and friends in more places
While investigating #12545, I discovered several places in the code that performed length-checks like so: ``` length ts == 4 ``` This is not ideal, since the length of `ts` could be much longer than 4, and we'd be doing way more work than necessary! There are already a slew of helper functions in `Util` such as `lengthIs` that are designed to do this efficiently, so I found every place where they ought to be used and did just that. I also defined a couple more utility functions for list length that were common patterns (e.g., `ltLength`). Test Plan: ./validate Reviewers: austin, hvr, goldfire, bgamari, simonmar Reviewed By: bgamari, simonmar Subscribers: goldfire, rwbarton, thomie Differential Revision: https://phabricator.haskell.org/D3622
Diffstat (limited to 'compiler/coreSyn')
-rw-r--r--compiler/coreSyn/CoreLint.hs12
-rw-r--r--compiler/coreSyn/CoreUnfold.hs4
-rw-r--r--compiler/coreSyn/CoreUtils.hs8
-rw-r--r--compiler/coreSyn/TrieMap.hs3
4 files changed, 14 insertions, 13 deletions
diff --git a/compiler/coreSyn/CoreLint.hs b/compiler/coreSyn/CoreLint.hs
index 0888afbeeb..2be1020674 100644
--- a/compiler/coreSyn/CoreLint.hs
+++ b/compiler/coreSyn/CoreLint.hs
@@ -566,7 +566,7 @@ lintSingleBinding top_lvl_flag rec_flag (binder,rhs)
-- Check that the binder's arity is within the bounds imposed by
-- the type and the strictness signature. See Note [exprArity invariant]
-- and Note [Trimming arity]
- ; checkL (idArity binder <= length (typeArity (idType binder)))
+ ; checkL (typeArity (idType binder) `lengthAtLeast` idArity binder)
(text "idArity" <+> ppr (idArity binder) <+>
text "exceeds typeArity" <+>
ppr (length (typeArity (idType binder))) <> colon <+>
@@ -574,7 +574,7 @@ lintSingleBinding top_lvl_flag rec_flag (binder,rhs)
; case splitStrictSig (idStrictness binder) of
(demands, result_info) | isBotRes result_info ->
- checkL (idArity binder <= length demands)
+ checkL (demands `lengthAtLeast` idArity binder)
(text "idArity" <+> ppr (idArity binder) <+>
text "exceeds arity imposed by the strictness signature" <+>
ppr (idStrictness binder) <> colon <+>
@@ -1288,12 +1288,12 @@ lintType ty@(TyConApp tc tys)
-- should be represented with the FunTy constructor. See Note [Linting
-- function types] and Note [Representation of function types].
| isFunTyCon tc
- , length tys == 4
+ , tys `lengthIs` 4
= failWithL (hang (text "Saturated application of (->)") 2 (ppr ty))
| isTypeSynonymTyCon tc || isTypeFamilyTyCon tc
-- Also type synonyms and type families
- , length tys < tyConArity tc
+ , tys `lengthLessThan` tyConArity tc
= failWithL (hang (text "Un-saturated type application") 2 (ppr ty))
| otherwise
@@ -1715,7 +1715,7 @@ lintCoercion the_co@(NthCo n co)
, isInjectiveTyCon tc_s r
-- see Note [NthCo and newtypes] in TyCoRep
, tys_s `equalLength` tys_t
- , n < length tys_s
+ , tys_s `lengthExceeds` n
-> return (ks, kt, ts, tt, tr)
where
ts = getNth tys_s n
@@ -1766,7 +1766,7 @@ lintCoercion co@(AxiomInstCo con ind cos)
, cab_roles = roles
, cab_lhs = lhs
, cab_rhs = rhs } = coAxiomNthBranch con ind
- ; unless (length ktvs + length cvs == length cos) $
+ ; unless (cos `equalLength` (ktvs ++ cvs)) $
bad_ax (text "lengths")
; subst <- getTCvSubst
; let empty_subst = zapTCvSubst subst
diff --git a/compiler/coreSyn/CoreUnfold.hs b/compiler/coreSyn/CoreUnfold.hs
index 811ddad00e..cedc78fcfa 100644
--- a/compiler/coreSyn/CoreUnfold.hs
+++ b/compiler/coreSyn/CoreUnfold.hs
@@ -578,7 +578,7 @@ sizeExpr dflags bOMB_OUT_SIZE top_args expr
foldr (addAltSize . size_up_alt) case_size alts
where
case_size
- | is_inline_scrut e, not (lengthExceeds alts 1) = sizeN (-10)
+ | is_inline_scrut e, lengthAtMost alts 1 = sizeN (-10)
| otherwise = sizeZero
-- Normally we don't charge for the case itself, but
-- we charge one per alternative (see size_up_alt,
@@ -593,7 +593,7 @@ sizeExpr dflags bOMB_OUT_SIZE top_args expr
-- case touch# x# of _ -> ... should cost 0
-- (see #4978)
--
- -- I would like to not have the "not (lengthExceeds alts 1)"
+ -- I would like to not have the "lengthAtMost alts 1"
-- condition above, but without that some programs got worse
-- (spectral/hartel/event and spectral/para). I don't fully
-- understand why. (SDM 24/5/11)
diff --git a/compiler/coreSyn/CoreUtils.hs b/compiler/coreSyn/CoreUtils.hs
index cc2d1724a5..b8399237da 100644
--- a/compiler/coreSyn/CoreUtils.hs
+++ b/compiler/coreSyn/CoreUtils.hs
@@ -1391,7 +1391,7 @@ altsAreExhaustive ((con1,_,_) : alts)
= case con1 of
DEFAULT -> True
LitAlt {} -> False
- DataAlt c -> 1 + length alts == tyConFamilySize (dataConTyCon c)
+ DataAlt c -> alts `lengthIs` (tyConFamilySize (dataConTyCon c) - 1)
-- It is possible to have an exhaustive case that does not
-- enumerate all constructors, notably in a GADT match, but
-- we behave conservatively here -- I don't think it's important
@@ -1783,7 +1783,7 @@ eqExpr in_scope e1 e2
&& go (rnBndr2 env v1 v2) e1 e2
go env (Let (Rec ps1) e1) (Let (Rec ps2) e2)
- = length ps1 == length ps2
+ = equalLength ps1 ps2
&& all2 (go env') rs1 rs2 && go env' e1 e2
where
(bs1,rs1) = unzip ps1
@@ -1838,7 +1838,7 @@ diffExpr top env (Let bs1 e1) (Let bs2 e2)
= let (ds, env') = diffBinds top env (flattenBinds [bs1]) (flattenBinds [bs2])
in ds ++ diffExpr top env' e1 e2
diffExpr top env (Case e1 b1 t1 a1) (Case e2 b2 t2 a2)
- | length a1 == length a2 && not (null a1) || eqTypeX env t1 t2
+ | equalLength a1 a2 && not (null a1) || eqTypeX env t1 t2
-- See Note [Empty case alternatives] in TrieMap
= diffExpr top env e1 e2 ++ concat (zipWith diffAlt a1 a2)
where env' = rnBndr2 env b1 b2
@@ -1933,7 +1933,7 @@ diffUnfold _ BootUnfolding BootUnfolding = []
diffUnfold _ (OtherCon cs1) (OtherCon cs2) | cs1 == cs2 = []
diffUnfold env (DFunUnfolding bs1 c1 a1)
(DFunUnfolding bs2 c2 a2)
- | c1 == c2 && length bs1 == length bs2
+ | c1 == c2 && equalLength bs1 bs2
= concatMap (uncurry (diffExpr False env')) (zip a1 a2)
where env' = rnBndrs2 env bs1 bs2
diffUnfold env (CoreUnfolding t1 _ _ v1 cl1 wf1 x1 g1)
diff --git a/compiler/coreSyn/TrieMap.hs b/compiler/coreSyn/TrieMap.hs
index 9058d03b57..a6b9db46cb 100644
--- a/compiler/coreSyn/TrieMap.hs
+++ b/compiler/coreSyn/TrieMap.hs
@@ -41,6 +41,7 @@ import Var
import UniqDFM
import Unique( Unique )
import FastString(FastString)
+import Util
import qualified Data.Map as Map
import qualified Data.IntMap as IntMap
@@ -526,7 +527,7 @@ instance Eq (DeBruijn CoreExpr) where
&& D (extendCME env1 v1) e1 == D (extendCME env2 v2) e2
go (Let (Rec ps1) e1) (Let (Rec ps2) e2)
- = length ps1 == length ps2
+ = equalLength ps1 ps2
&& D env1' rs1 == D env2' rs2
&& D env1' e1 == D env2' e2
where