summaryrefslogtreecommitdiff
path: root/compiler/rename
diff options
context:
space:
mode:
authorRyan Scott <ryan.gl.scott@gmail.com>2017-08-12 15:47:27 -0400
committerRyan Scott <ryan.gl.scott@gmail.com>2017-08-12 15:47:27 -0400
commit7d699782bf6148c115a49b5f31ada9bd7c32a7d6 (patch)
tree5307e48a467a74c8d068117aba0d2d0bcce57742 /compiler/rename
parent3f05e5f6becc2f7174898726b6f027105b12a780 (diff)
downloadhaskell-7d699782bf6148c115a49b5f31ada9bd7c32a7d6.tar.gz
Use NonEmpty lists to represent lists of duplicate elements
Summary: Three functions in `ListSetOps` which compute duplicate elements represent lists of duplicates of `[a]`. This is a really bad way to go about things, because these lists are guaranteed to always have at least one element (the "representative" of the duplicates), and several places in the GHC API call `head` (a partial function) on these lists of duplicates to retrieve the representative. This changes the representation of duplicates to `NonEmpty` lists instead, which allow for many partial uses of `head` to be made total. Fixes #13823. Test Plan: ./validate Reviewers: bgamari, austin, goldfire Reviewed By: bgamari Subscribers: goldfire, rwbarton, thomie GHC Trac Issues: #13823 Differential Revision: https://phabricator.haskell.org/D3823
Diffstat (limited to 'compiler/rename')
-rw-r--r--compiler/rename/RnBinds.hs17
-rw-r--r--compiler/rename/RnExpr.hs3
-rw-r--r--compiler/rename/RnPat.hs9
-rw-r--r--compiler/rename/RnSource.hs21
-rw-r--r--compiler/rename/RnTypes.hs7
-rw-r--r--compiler/rename/RnUtils.hs7
6 files changed, 36 insertions, 28 deletions
diff --git a/compiler/rename/RnBinds.hs b/compiler/rename/RnBinds.hs
index 47bd0d9b79..b956a5adda 100644
--- a/compiler/rename/RnBinds.hs
+++ b/compiler/rename/RnBinds.hs
@@ -58,7 +58,9 @@ import Maybes ( orElse )
import qualified GHC.LanguageExtensions as LangExt
import Control.Monad
-import Data.List ( partition, sort )
+import Data.Foldable ( toList )
+import Data.List ( partition, sort )
+import Data.List.NonEmpty ( NonEmpty(..) )
{-
-- ToDo: Put the annotations into the monad, so that they arrive in the proper
@@ -1091,7 +1093,7 @@ okHsSig ctxt (L _ sig)
(CompleteMatchSig {}, _) -> False
-------------------
-findDupSigs :: [LSig GhcPs] -> [[(Located RdrName, Sig GhcPs)]]
+findDupSigs :: [LSig GhcPs] -> [NonEmpty (Located RdrName, Sig GhcPs)]
-- Check for duplicates on RdrName version,
-- because renamed version has unboundName for
-- not-in-scope binders, which gives bogus dup-sig errors
@@ -1243,17 +1245,18 @@ rnGRHS' ctxt rnBody (GRHS guards rhs)
************************************************************************
-}
-dupSigDeclErr :: [(Located RdrName, Sig GhcPs)] -> RnM ()
-dupSigDeclErr pairs@((L loc name, sig) : _)
+dupSigDeclErr :: NonEmpty (Located RdrName, Sig GhcPs) -> RnM ()
+dupSigDeclErr pairs@((L loc name, sig) :| _)
= addErrAt loc $
vcat [ text "Duplicate" <+> what_it_is
<> text "s for" <+> quotes (ppr name)
- , text "at" <+> vcat (map ppr $ sort $ map (getLoc . fst) pairs) ]
+ , text "at" <+> vcat (map ppr $ sort
+ $ map (getLoc . fst)
+ $ toList pairs)
+ ]
where
what_it_is = hsSigDoc sig
-dupSigDeclErr [] = panic "dupSigDeclErr"
-
misplacedSigErr :: LSig GhcRn -> RnM ()
misplacedSigErr (L loc sig)
= addErrAt loc $
diff --git a/compiler/rename/RnExpr.hs b/compiler/rename/RnExpr.hs
index 0e2022da47..6eabc8969d 100644
--- a/compiler/rename/RnExpr.hs
+++ b/compiler/rename/RnExpr.hs
@@ -57,6 +57,7 @@ import qualified GHC.LanguageExtensions as LangExt
import Data.Ord
import Data.Array
+import qualified Data.List.NonEmpty as NE
{-
************************************************************************
@@ -970,7 +971,7 @@ rnParallelStmts ctxt return_op segs thing_inside
cmpByOcc n1 n2 = nameOccName n1 `compare` nameOccName n2
dupErr vs = addErr (text "Duplicate binding in parallel list comprehension for:"
- <+> quotes (ppr (head vs)))
+ <+> quotes (ppr (NE.head vs)))
lookupStmtName :: HsStmtContext Name -> Name -> RnM (SyntaxExpr GhcRn, FreeVars)
-- Like lookupSyntaxName, but respects contexts
diff --git a/compiler/rename/RnPat.hs b/compiler/rename/RnPat.hs
index ff88dbffbc..320e4f3d12 100644
--- a/compiler/rename/RnPat.hs
+++ b/compiler/rename/RnPat.hs
@@ -68,6 +68,7 @@ import DataCon
import qualified GHC.LanguageExtensions as LangExt
import Control.Monad ( when, liftM, ap, unless )
+import qualified Data.List.NonEmpty as NE
import Data.Ratio
{-
@@ -690,7 +691,7 @@ rnHsRecFields ctxt mk_arg (HsRecFields { rec_flds = flds, rec_dotdot = dotdot })
-- Data constructor not lexically in scope at all
-- See Note [Disambiguation and Template Haskell]
- dup_flds :: [[RdrName]]
+ dup_flds :: [NE.NonEmpty RdrName]
-- Each list represents a RdrName that occurred more than once
-- (the list contains all occurrences)
-- Each list in dup_fields is non-empty
@@ -769,7 +770,7 @@ rnHsRecUpdFields flds
, hsRecFieldArg = arg''
, hsRecPun = pun }), fvs') }
- dup_flds :: [[RdrName]]
+ dup_flds :: [NE.NonEmpty RdrName]
-- Each list represents a RdrName that occurred more than once
-- (the list contains all occurrences)
-- Each list in dup_fields is non-empty
@@ -803,10 +804,10 @@ badPun :: Located RdrName -> SDoc
badPun fld = vcat [text "Illegal use of punning for field" <+> quotes (ppr fld),
text "Use NamedFieldPuns to permit this"]
-dupFieldErr :: HsRecFieldContext -> [RdrName] -> SDoc
+dupFieldErr :: HsRecFieldContext -> NE.NonEmpty RdrName -> SDoc
dupFieldErr ctxt dups
= hsep [text "duplicate field name",
- quotes (ppr (head dups)),
+ quotes (ppr (NE.head dups)),
text "in record", pprRFC ctxt]
pprRFC :: HsRecFieldContext -> SDoc
diff --git a/compiler/rename/RnSource.hs b/compiler/rename/RnSource.hs
index 244f46b3c0..0956d6f328 100644
--- a/compiler/rename/RnSource.hs
+++ b/compiler/rename/RnSource.hs
@@ -63,7 +63,9 @@ import qualified GHC.LanguageExtensions as LangExt
import Control.Monad
import Control.Arrow ( first )
-import Data.List ( sortBy, mapAccumL )
+import Data.List ( mapAccumL )
+import qualified Data.List.NonEmpty as NE
+import Data.List.NonEmpty ( NonEmpty(..) )
import Data.Maybe ( isJust )
import qualified Data.Set as Set ( difference, fromList, toList, null )
@@ -320,7 +322,7 @@ rnSrcWarnDecls _ []
rnSrcWarnDecls bndr_set decls'
= do { -- check for duplicates
- ; mapM_ (\ dups -> let (L loc rdr:lrdr':_) = dups
+ ; mapM_ (\ dups -> let (L loc rdr :| (lrdr':_)) = dups
in addErrAt loc (dupWarnDecl lrdr' rdr))
warn_rdr_dups
; pairs_s <- mapM (addLocM rn_deprec) decls
@@ -341,7 +343,7 @@ rnSrcWarnDecls bndr_set decls'
warn_rdr_dups = findDupRdrNames $ concatMap (\(L _ (Warning ns _)) -> ns)
decls
-findDupRdrNames :: [Located RdrName] -> [[Located RdrName]]
+findDupRdrNames :: [Located RdrName] -> [NonEmpty (Located RdrName)]
findDupRdrNames = findDupsEq (\ x -> \ y -> rdrNameOcc (unLoc x) == rdrNameOcc (unLoc y))
-- look for duplicates among the OccNames;
@@ -745,11 +747,11 @@ rnFamInstDecl doc mb_cls tycon (HsIB { hsib_body = pats }) payload rnPayload
-- Report unused binders on the LHS
-- See Note [Unused type variables in family instances]
- ; let groups :: [[Located RdrName]]
+ ; let groups :: [NonEmpty (Located RdrName)]
groups = equivClasses cmpLocated $
freeKiTyVarsAllVars pat_kity_vars_with_dups
; tv_nms_dups <- mapM (lookupOccRn . unLoc) $
- [ tv | (tv:_:_) <- groups ]
+ [ tv | (tv :| (_:_)) <- groups ]
-- Add to the used variables
-- a) any variables that appear *more than once* on the LHS
-- e.g. F a Int a = Bool
@@ -1530,16 +1532,15 @@ rnRoleAnnots tc_names role_annots
tycon
; return $ RoleAnnotDecl tycon' roles }
-dupRoleAnnotErr :: [LRoleAnnotDecl GhcPs] -> RnM ()
-dupRoleAnnotErr [] = panic "dupRoleAnnotErr"
+dupRoleAnnotErr :: NonEmpty (LRoleAnnotDecl GhcPs) -> RnM ()
dupRoleAnnotErr list
= addErrAt loc $
hang (text "Duplicate role annotations for" <+>
quotes (ppr $ roleAnnotDeclName first_decl) <> colon)
- 2 (vcat $ map pp_role_annot sorted_list)
+ 2 (vcat $ map pp_role_annot $ NE.toList sorted_list)
where
- sorted_list = sortBy cmp_annot list
- (L loc first_decl : _) = sorted_list
+ sorted_list = NE.sortBy cmp_annot list
+ (L loc first_decl :| _) = sorted_list
pp_role_annot (L loc decl) = hang (ppr decl)
4 (text "-- written at" <+> ppr loc)
diff --git a/compiler/rename/RnTypes.hs b/compiler/rename/RnTypes.hs
index 5f52d2fe1c..cfe1517c50 100644
--- a/compiler/rename/RnTypes.hs
+++ b/compiler/rename/RnTypes.hs
@@ -62,8 +62,9 @@ import FastString
import Maybes
import qualified GHC.LanguageExtensions as LangExt
-import Data.List ( nubBy, partition )
-import Control.Monad ( unless, when )
+import Data.List ( nubBy, partition )
+import Data.List.NonEmpty ( NonEmpty(..) )
+import Control.Monad ( unless, when )
#include "HsVersions.h"
@@ -974,7 +975,7 @@ bindLHsTyVarBndr doc mb_assoc kv_names tv_names hs_tv_bndr thing_inside
addErrAt loc (vcat [ ki_ty_err_msg name
, pprHsDocContext doc ])
; when (name `elemNameSet` tv_names) $
- dupNamesErr getLoc [L loc name, L (nameSrcSpan name) name] }}
+ dupNamesErr getLoc (L loc name :| [L (nameSrcSpan name) name]) }}
ki_ty_err_msg n = text "Variable" <+> quotes (ppr n) <+>
text "used as a kind variable before being bound" $$
diff --git a/compiler/rename/RnUtils.hs b/compiler/rename/RnUtils.hs
index 7b2f74f1da..50598f8b49 100644
--- a/compiler/rename/RnUtils.hs
+++ b/compiler/rename/RnUtils.hs
@@ -45,6 +45,7 @@ import FastString
import Control.Monad
import Data.List
import Constants ( mAX_TUPLE_SIZE )
+import qualified Data.List.NonEmpty as NE
import qualified GHC.LanguageExtensions as LangExt
{-
@@ -316,13 +317,13 @@ unknownSubordinateErr doc op -- Doc is "method of class" or
= quotes (ppr op) <+> text "is not a (visible)" <+> doc
-dupNamesErr :: Outputable n => (n -> SrcSpan) -> [n] -> RnM ()
+dupNamesErr :: Outputable n => (n -> SrcSpan) -> NE.NonEmpty n -> RnM ()
dupNamesErr get_loc names
= addErrAt big_loc $
- vcat [text "Conflicting definitions for" <+> quotes (ppr (head names)),
+ vcat [text "Conflicting definitions for" <+> quotes (ppr (NE.head names)),
locations]
where
- locs = map get_loc names
+ locs = map get_loc (NE.toList names)
big_loc = foldr1 combineSrcSpans locs
locations = text "Bound at:" <+> vcat (map ppr (sort locs))