summaryrefslogtreecommitdiff
path: root/compiler/typecheck
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/typecheck
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/typecheck')
-rw-r--r--compiler/typecheck/FamInst.hs2
-rw-r--r--compiler/typecheck/FunDeps.hs4
-rw-r--r--compiler/typecheck/TcCanonical.hs2
-rw-r--r--compiler/typecheck/TcDeriv.hs6
-rw-r--r--compiler/typecheck/TcDerivInfer.hs8
-rw-r--r--compiler/typecheck/TcErrors.hs6
-rw-r--r--compiler/typecheck/TcFlatten.hs2
-rw-r--r--compiler/typecheck/TcGenDeriv.hs4
-rw-r--r--compiler/typecheck/TcGenGenerics.hs6
-rw-r--r--compiler/typecheck/TcPat.hs2
-rw-r--r--compiler/typecheck/TcSplice.hs4
-rw-r--r--compiler/typecheck/TcTyClsDecls.hs4
-rw-r--r--compiler/typecheck/TcUnify.hs2
-rw-r--r--compiler/typecheck/TcValidity.hs12
14 files changed, 32 insertions, 32 deletions
diff --git a/compiler/typecheck/FamInst.hs b/compiler/typecheck/FamInst.hs
index f69e41209f..cabfb3376b 100644
--- a/compiler/typecheck/FamInst.hs
+++ b/compiler/typecheck/FamInst.hs
@@ -789,7 +789,7 @@ isTFHeaded ty | Just ty' <- coreView ty
= isTFHeaded ty'
isTFHeaded ty | (TyConApp tc args) <- ty
, isTypeFamilyTyCon tc
- = tyConArity tc == length args
+ = args `lengthIs` tyConArity tc
isTFHeaded _ = False
diff --git a/compiler/typecheck/FunDeps.hs b/compiler/typecheck/FunDeps.hs
index fff8979e0d..789254d230 100644
--- a/compiler/typecheck/FunDeps.hs
+++ b/compiler/typecheck/FunDeps.hs
@@ -255,8 +255,8 @@ improveClsFD clas_tvs fd
= [] -- Filter out ones that can't possibly match,
| otherwise
- = ASSERT2( length tys_inst == length tys_actual &&
- length tys_inst == length clas_tvs
+ = ASSERT2( equalLength tys_inst tys_actual &&
+ equalLength tys_inst clas_tvs
, ppr tys_inst <+> ppr tys_actual )
case tcMatchTyKis ltys1 ltys2 of
diff --git a/compiler/typecheck/TcCanonical.hs b/compiler/typecheck/TcCanonical.hs
index 77bf63d98e..ff00d4220b 100644
--- a/compiler/typecheck/TcCanonical.hs
+++ b/compiler/typecheck/TcCanonical.hs
@@ -917,7 +917,7 @@ canTyConApp :: CtEvidence -> EqRel
-- See Note [Decomposing TyConApps]
canTyConApp ev eq_rel tc1 tys1 tc2 tys2
| tc1 == tc2
- , length tys1 == length tys2
+ , tys1 `equalLength` tys2
= do { inerts <- getTcSInerts
; if can_decompose inerts
then do { traceTcS "canTyConApp"
diff --git a/compiler/typecheck/TcDeriv.hs b/compiler/typecheck/TcDeriv.hs
index 8076115b6c..5bdfae70ac 100644
--- a/compiler/typecheck/TcDeriv.hs
+++ b/compiler/typecheck/TcDeriv.hs
@@ -613,7 +613,7 @@ deriveTyData tvs tc tc_args deriv_strat deriv_pred
-- Typeable is special, because Typeable :: forall k. k -> Constraint
-- so the argument kind 'k' is not decomposable by splitKindFunTys
-- as is the case for all other derivable type classes
- ; when (length cls_arg_kinds /= 1) $
+ ; when (cls_arg_kinds `lengthIsNot` 1) $
failWithTc (nonUnaryErr deriv_pred)
; let [cls_arg_kind] = cls_arg_kinds
; if className cls == typeableClassName
@@ -1101,7 +1101,7 @@ mkNewTypeEqn dflags overlap_mode tvs
cls cls_tys tycon tc_args rep_tycon rep_tc_args
mtheta deriv_strat
-- Want: instance (...) => cls (cls_tys ++ [tycon tc_args]) where ...
- = ASSERT( length cls_tys + 1 == classArity cls )
+ = ASSERT( cls_tys `lengthIs` (classArity cls - 1) )
case deriv_strat of
Just StockStrategy -> mk_eqn_stock dflags mtheta cls cls_tys rep_tycon
go_for_it_other bale_out
@@ -1302,7 +1302,7 @@ mkNewTypeEqn dflags overlap_mode tvs
&& isNothing at_without_last_cls_tv
-- Check that eta reduction is OK
- eta_ok = nt_eta_arity <= length rep_tc_args
+ eta_ok = rep_tc_args `lengthAtLeast` nt_eta_arity
-- The newtype can be eta-reduced to match the number
-- of type argument actually supplied
-- newtype T a b = MkT (S [a] b) deriving( Monad )
diff --git a/compiler/typecheck/TcDerivInfer.hs b/compiler/typecheck/TcDerivInfer.hs
index 93dcf4383c..02c0103eec 100644
--- a/compiler/typecheck/TcDerivInfer.hs
+++ b/compiler/typecheck/TcDerivInfer.hs
@@ -67,12 +67,12 @@ inferConstraints :: [TyVar] -> Class -> [TcType] -> TcType
inferConstraints tvs main_cls cls_tys inst_ty
rep_tc rep_tc_args
mechanism
- | is_generic && not is_anyclass -- Generic constraints are easy
+ | is_generic && not is_anyclass -- Generic constraints are easy
= return ([], tvs, inst_tys)
- | is_generic1 && not is_anyclass -- Generic1 needs Functor
- = ASSERT( length rep_tc_tvs > 0 ) -- See Note [Getting base classes]
- ASSERT( length cls_tys == 1 ) -- Generic1 has a single kind variable
+ | is_generic1 && not is_anyclass -- Generic1 needs Functor
+ = ASSERT( rep_tc_tvs `lengthExceeds` 0 ) -- See Note [Getting base classes]
+ ASSERT( cls_tys `lengthIs` 1 ) -- Generic1 has a single kind variable
do { functorClass <- tcLookupClass functorClassName
; con_arg_constraints (get_gen1_constraints functorClass) }
diff --git a/compiler/typecheck/TcErrors.hs b/compiler/typecheck/TcErrors.hs
index 324391f68b..4411d6ac51 100644
--- a/compiler/typecheck/TcErrors.hs
+++ b/compiler/typecheck/TcErrors.hs
@@ -1548,7 +1548,7 @@ mkCoercibleExplanation rdr_env fam_envs ty1 ty2
has_unknown_roles ty
| Just (tc, tys) <- tcSplitTyConApp_maybe ty
- = length tys >= tyConArity tc -- oversaturated tycon
+ = tys `lengthAtLeast` tyConArity tc -- oversaturated tycon
| Just (s, _) <- tcSplitAppTy_maybe ty
= has_unknown_roles s
| isTyVarTy ty
@@ -2503,7 +2503,7 @@ mk_dict_err ctxt@(CEC {cec_encl = implics}) (ct, (matches, unifiers, unsafe_over
-- Overlap error because of Safe Haskell (first
-- match should be the most specific match)
safe_haskell_msg
- = ASSERT( length matches == 1 && not (null unsafe_ispecs) )
+ = ASSERT( matches `lengthIs` 1 && not (null unsafe_ispecs) )
vcat [ addArising orig (text "Unsafe overlapping instances for"
<+> pprType (mkClassPred clas tys))
, sep [text "The matching instance is:",
@@ -2706,7 +2706,7 @@ pprPotentials dflags sty herald insts
<+> text "involving out-of-scope types")
2 (ppWhen show_potentials (pprInstances not_in_scope))
- flag_hint = ppUnless (show_potentials || length show_these == length insts) $
+ flag_hint = ppUnless (show_potentials || equalLength show_these insts) $
text "(use -fprint-potential-instances to see them all)"
{- Note [Displaying potential instances]
diff --git a/compiler/typecheck/TcFlatten.hs b/compiler/typecheck/TcFlatten.hs
index 650cbd8219..1bb4a7165b 100644
--- a/compiler/typecheck/TcFlatten.hs
+++ b/compiler/typecheck/TcFlatten.hs
@@ -1132,7 +1132,7 @@ flatten_fam_app :: TyCon -> [TcType] -> FlatM (Xi, Coercion)
-- flatten_exact_fam_app_fully lifts out the application to top level
-- Postcondition: Coercion :: Xi ~ F tys
flatten_fam_app tc tys -- Can be over-saturated
- = ASSERT2( tyConArity tc <= length tys
+ = ASSERT2( tys `lengthAtLeast` tyConArity tc
, ppr tc $$ ppr (tyConArity tc) $$ ppr tys)
-- Type functions are saturated
-- The type function might be *over* saturated
diff --git a/compiler/typecheck/TcGenDeriv.hs b/compiler/typecheck/TcGenDeriv.hs
index d8fb62044b..d46b67c248 100644
--- a/compiler/typecheck/TcGenDeriv.hs
+++ b/compiler/typecheck/TcGenDeriv.hs
@@ -381,7 +381,7 @@ gen_Ord_binds loc tycon = do
mkOrdOpRhs :: DynFlags -> OrdOp -> LHsExpr RdrName
mkOrdOpRhs dflags op -- RHS for comparing 'a' and 'b' according to op
- | length nullary_cons <= 2 -- Two nullary or fewer, so use cases
+ | nullary_cons `lengthAtMost` 2 -- Two nullary or fewer, so use cases
= nlHsCase (nlHsVar a_RDR) $
map (mkOrdOpAlt dflags op) tycon_data_cons
-- i.e. case a of { C1 x y -> case b of C1 x y -> ....compare x,y...
@@ -1027,7 +1027,7 @@ gen_Read_binds get_fixity loc tycon
labels = map flLabel $ dataConFieldLabels data_con
dc_nm = getName data_con
is_infix = dataConIsInfix data_con
- is_record = length labels > 0
+ is_record = labels `lengthExceeds` 0
as_needed = take con_arity as_RDRs
read_args = zipWithEqual "gen_Read_binds" read_arg as_needed (dataConOrigArgTys data_con)
(read_a1:read_a2:_) = read_args
diff --git a/compiler/typecheck/TcGenGenerics.hs b/compiler/typecheck/TcGenGenerics.hs
index 51451a6d1a..fc0209d805 100644
--- a/compiler/typecheck/TcGenGenerics.hs
+++ b/compiler/typecheck/TcGenGenerics.hs
@@ -348,7 +348,7 @@ mkBindsRep gk tycon =
(from_alts, to_alts) = mkSum gk_ (1 :: US) datacons
where gk_ = case gk of
Gen0 -> Gen0_
- Gen1 -> ASSERT(length tyvars >= 1)
+ Gen1 -> ASSERT(tyvars `lengthAtLeast` 1)
Gen1_ (last tyvars)
where tyvars = tyConTyVars tycon
@@ -572,7 +572,7 @@ tc_mkRepTy gk_ tycon k =
prod :: [Type] -> [HsSrcBang] -> [HsImplBang] -> [FieldLabel] -> Type
prod [] _ _ _ = mkTyConApp u1 [k]
prod l sb ib fl = foldBal mkProd
- [ ASSERT(null fl || length fl > j)
+ [ ASSERT(null fl || lengthExceeds fl j)
arg t sb' ib' (if null fl
then Nothing
else Just (fl !! j))
@@ -617,7 +617,7 @@ tc_mkRepTy gk_ tycon k =
buildFix n assoc = mkTyConApp pInfix [ mkTyConTy assoc
, mkNumLitTy (fromIntegral n)]
- isRec c = mkTyConTy $ if length (dataConFieldLabels c) > 0
+ isRec c = mkTyConTy $ if dataConFieldLabels c `lengthExceeds` 0
then promotedTrueDataCon
else promotedFalseDataCon
diff --git a/compiler/typecheck/TcPat.hs b/compiler/typecheck/TcPat.hs
index 486210cb07..07f945ccf3 100644
--- a/compiler/typecheck/TcPat.hs
+++ b/compiler/typecheck/TcPat.hs
@@ -468,7 +468,7 @@ tc_pat penv (TuplePat pats boxity _) pat_ty thing_inside
| otherwise = unmangled_result
; pat_ty <- readExpType pat_ty
- ; ASSERT( length con_arg_tys == length pats ) -- Syntactically enforced
+ ; ASSERT( con_arg_tys `equalLength` pats ) -- Syntactically enforced
return (mkHsWrapPat coi possibly_mangled_result pat_ty, res)
}
diff --git a/compiler/typecheck/TcSplice.hs b/compiler/typecheck/TcSplice.hs
index 962ad2e0e0..b989aa18d6 100644
--- a/compiler/typecheck/TcSplice.hs
+++ b/compiler/typecheck/TcSplice.hs
@@ -1468,7 +1468,7 @@ reifyDataCon isGadtDataCon tys dc
-- constructors can be declared infix.
-- See Note [Infix GADT constructors] in TcTyClsDecls.
| dataConIsInfix dc && not isGadtDataCon ->
- ASSERT( length arg_tys == 2 ) do
+ ASSERT( arg_tys `lengthIs` 2 ) do
{ let [r_a1, r_a2] = r_arg_tys
[s1, s2] = dcdBangs
; return $ TH.InfixC (s1,r_a1) name (s2,r_a2) }
@@ -1486,7 +1486,7 @@ reifyDataCon isGadtDataCon tys dc
{ cxt <- reifyCxt theta'
; ex_tvs'' <- reifyTyVars ex_tvs' Nothing
; return (TH.ForallC ex_tvs'' cxt main_con) }
- ; ASSERT( length arg_tys == length dcdBangs )
+ ; ASSERT( arg_tys `equalLength` dcdBangs )
ret_con }
-- Note [Reifying GADT data constructors]
diff --git a/compiler/typecheck/TcTyClsDecls.hs b/compiler/typecheck/TcTyClsDecls.hs
index cb46c69832..6076c75f30 100644
--- a/compiler/typecheck/TcTyClsDecls.hs
+++ b/compiler/typecheck/TcTyClsDecls.hs
@@ -1087,7 +1087,7 @@ tcDefaultAssocDecl fam_tc [L loc (TyFamEqn { tfe_tycon = L _ tc_name
checkTc (isTypeFamilyTyCon fam_tc) (wrongKindOfFamily fam_tc)
-- Arity check
- ; checkTc (length exp_vars == fam_arity)
+ ; checkTc (exp_vars `lengthIs` fam_arity)
(wrongNumberOfParmsErr fam_arity)
-- Typecheck RHS
@@ -2295,7 +2295,7 @@ checkValidTyConTyVars tc
2 (vcat (map pp_tv stripped_tvs)) ])) }
where
tvs = tyConTyVars tc
- duplicate_vars = sizeVarSet (mkVarSet tvs) < length tvs
+ duplicate_vars = tvs `lengthExceeds` sizeVarSet (mkVarSet tvs)
pp_tv tv = ppr tv <+> dcolon <+> ppr (tyVarKind tv)
diff --git a/compiler/typecheck/TcUnify.hs b/compiler/typecheck/TcUnify.hs
index f106268455..a1a2add2b7 100644
--- a/compiler/typecheck/TcUnify.hs
+++ b/compiler/typecheck/TcUnify.hs
@@ -1329,7 +1329,7 @@ uType origin t_or_k orig_ty1 orig_ty2
go (TyConApp tc1 tys1) (TyConApp tc2 tys2)
-- See Note [Mismatched type lists and application decomposition]
- | tc1 == tc2, length tys1 == length tys2
+ | tc1 == tc2, equalLength tys1 tys2
= ASSERT2( isGenerativeTyCon tc1 Nominal, ppr tc1 )
do { cos <- zipWithM (uType origin t_or_k) tys1 tys2
; return $ mkTyConAppCo Nominal tc1 cos }
diff --git a/compiler/typecheck/TcValidity.hs b/compiler/typecheck/TcValidity.hs
index 0a7a0adf7f..a938d12a08 100644
--- a/compiler/typecheck/TcValidity.hs
+++ b/compiler/typecheck/TcValidity.hs
@@ -504,7 +504,7 @@ check_syn_tc_app :: TidyEnv -> UserTypeCtxt -> Rank -> KindOrType
-- which must be saturated,
-- but not data families, which need not be saturated
check_syn_tc_app env ctxt rank ty tc tys
- | tc_arity <= length tys -- Saturated
+ | tys `lengthAtLeast` tc_arity -- Saturated
-- Check that the synonym has enough args
-- This applies equally to open and closed synonyms
-- It's OK to have an *over-applied* type synonym
@@ -739,7 +739,7 @@ check_eq_pred :: TidyEnv -> DynFlags -> PredType -> TyCon -> [TcType] -> TcM ()
check_eq_pred env dflags pred tc tys
= -- Equational constraints are valid in all contexts if type
-- families are permitted
- do { checkTc (length tys == tyConArity tc) (tyConArityErr tc tys)
+ do { checkTc (tys `lengthIs` tyConArity tc) (tyConArityErr tc tys)
; checkTcM (xopt LangExt.TypeFamilies dflags
|| xopt LangExt.GADTs dflags)
(eqPredTyErr env pred) }
@@ -814,7 +814,7 @@ check_class_pred env dflags ctxt pred cls tys
; when warn_simp check_simplifiable_class_constraint
; checkTcM arg_tys_ok (predTyVarErr env pred) }
where
- check_arity = checkTc (classArity cls == length tys)
+ check_arity = checkTc (tys `lengthIs` classArity cls)
(tyConArityErr (classTyCon cls) tys)
-- Check the arguments of a class constraint
@@ -1047,7 +1047,7 @@ checkValidInstHead ctxt clas cls_args
all tcInstHeadTyAppAllTyVars ty_args)
(instTypeErr clas cls_args head_type_args_tyvars_msg)
; checkTc (xopt LangExt.MultiParamTypeClasses dflags ||
- length ty_args == 1 || -- Only count type arguments
+ lengthIs ty_args 1 || -- Only count type arguments
(xopt LangExt.NullaryTypeClasses dflags &&
null ty_args))
(instTypeErr clas cls_args head_one_type_msg) }
@@ -1239,7 +1239,7 @@ validDerivPred tv_set pred
check_tys cls tys
= hasNoDups fvs
-- use sizePred to ignore implicit args
- && sizePred pred == fromIntegral (length fvs)
+ && lengthIs fvs (sizePred pred)
&& all (`elemVarSet` tv_set) fvs
where tys' = filterOutInvisibleTypes (classTyCon cls) tys
fvs = fvTypes tys'
@@ -1738,7 +1738,7 @@ checkValidFamPats mb_clsinfo fam_tc tvs cvs ty_pats
-- type family F a :: * -> *
-- type instance F Int y = y
-- because then the type (F Int) would be like (\y.y)
- checkTc (length ty_pats == fam_arity) $
+ checkTc (ty_pats `lengthIs` fam_arity) $
wrongNumberOfParmsErr (fam_arity - count isInvisibleTyConBinder fam_bndrs)
-- report only explicit arguments