summaryrefslogtreecommitdiff
path: root/compiler/rename/RnPat.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rename/RnPat.hs')
-rw-r--r--compiler/rename/RnPat.hs214
1 files changed, 88 insertions, 126 deletions
diff --git a/compiler/rename/RnPat.hs b/compiler/rename/RnPat.hs
index ff88dbffbc..6195309cab 100644
--- a/compiler/rename/RnPat.hs
+++ b/compiler/rename/RnPat.hs
@@ -11,6 +11,8 @@ free variables.
-}
{-# LANGUAGE CPP, RankNTypes, ScopedTypeVariables #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeFamilies #-}
module RnPat (-- main entry points
rnPat, rnPats, rnBindPat, rnPatAndThen,
@@ -35,6 +37,8 @@ module RnPat (-- main entry points
-- ENH: thin imports to only what is necessary for patterns
+import GhcPrelude
+
import {-# SOURCE #-} RnExpr ( rnLExpr )
import {-# SOURCE #-} RnSplice ( rnSplicePat )
@@ -47,13 +51,10 @@ import RnEnv
import RnFixity
import RnUtils ( HsDocContext(..), newLocalBndrRn, bindLocalNames
, warnUnusedMatches, newLocalBndrRn
- , checkDupAndShadowedNames, checkTupSize
- , unknownSubordinateErr )
+ , checkDupNames, checkDupAndShadowedNames
+ , checkTupSize , unknownSubordinateErr )
import RnTypes
import PrelNames
-import TyCon ( tyConName )
-import ConLike
-import Type ( TyThing(..) )
import Name
import NameSet
import RdrName
@@ -67,7 +68,8 @@ import TysWiredIn ( nilDataCon )
import DataCon
import qualified GHC.LanguageExtensions as LangExt
-import Control.Monad ( when, liftM, ap, unless )
+import Control.Monad ( when, liftM, ap, guard )
+import qualified Data.List.NonEmpty as NE
import Data.Ratio
{-
@@ -320,10 +322,11 @@ rnPats ctxt pats thing_inside
-- complain *twice* about duplicates e.g. f (x,x) = ...
--
-- See note [Don't report shadowing for pattern synonyms]
- ; unless (isPatSynCtxt ctxt)
- (addErrCtxt doc_pat $
- checkDupAndShadowedNames envs_before $
- collectPatsBinders pats')
+ ; let bndrs = collectPatsBinders pats'
+ ; addErrCtxt doc_pat $
+ if isPatSynCtxt ctxt
+ then checkDupNames bndrs
+ else checkDupAndShadowedNames envs_before bndrs
; thing_inside pats' } }
where
doc_pat = text "In" <+> pprMatchContext ctxt
@@ -377,17 +380,20 @@ rnLPatAndThen :: NameMaker -> LPat GhcPs -> CpsRn (LPat GhcRn)
rnLPatAndThen nm lpat = wrapSrcSpanCps (rnPatAndThen nm) lpat
rnPatAndThen :: NameMaker -> Pat GhcPs -> CpsRn (Pat GhcRn)
-rnPatAndThen _ (WildPat _) = return (WildPat placeHolderType)
-rnPatAndThen mk (ParPat pat) = do { pat' <- rnLPatAndThen mk pat; return (ParPat pat') }
-rnPatAndThen mk (LazyPat pat) = do { pat' <- rnLPatAndThen mk pat; return (LazyPat pat') }
-rnPatAndThen mk (BangPat pat) = do { pat' <- rnLPatAndThen mk pat; return (BangPat pat') }
-rnPatAndThen mk (VarPat (L l rdr)) = do { loc <- liftCps getSrcSpanM
- ; name <- newPatName mk (L loc rdr)
- ; return (VarPat (L l name)) }
+rnPatAndThen _ (WildPat _) = return (WildPat noExt)
+rnPatAndThen mk (ParPat x pat) = do { pat' <- rnLPatAndThen mk pat
+ ; return (ParPat x pat') }
+rnPatAndThen mk (LazyPat x pat) = do { pat' <- rnLPatAndThen mk pat
+ ; return (LazyPat x pat') }
+rnPatAndThen mk (BangPat x pat) = do { pat' <- rnLPatAndThen mk pat
+ ; return (BangPat x pat') }
+rnPatAndThen mk (VarPat x (L l rdr)) = do { loc <- liftCps getSrcSpanM
+ ; name <- newPatName mk (L loc rdr)
+ ; return (VarPat x (L l name)) }
-- we need to bind pattern variables for view pattern expressions
-- (e.g. in the pattern (x, x -> y) x needs to be bound in the rhs of the tuple)
-rnPatAndThen mk (SigPatIn pat sig)
+rnPatAndThen mk (SigPat sig pat )
-- When renaming a pattern type signature (e.g. f (a :: T) = ...), it is
-- important to rename its type signature _before_ renaming the rest of the
-- pattern, so that type variables are first bound by the _outermost_ pattern
@@ -399,21 +405,21 @@ rnPatAndThen mk (SigPatIn pat sig)
-- ~~~~~~~~~~~~~~~^ the same `a' then used here
= do { sig' <- rnHsSigCps sig
; pat' <- rnLPatAndThen mk pat
- ; return (SigPatIn pat' sig') }
+ ; return (SigPat sig' pat' ) }
-rnPatAndThen mk (LitPat lit)
+rnPatAndThen mk (LitPat x lit)
| HsString src s <- lit
= do { ovlStr <- liftCps (xoptM LangExt.OverloadedStrings)
; if ovlStr
then rnPatAndThen mk
- (mkNPat (noLoc (mkHsIsString src s placeHolderType))
+ (mkNPat (noLoc (mkHsIsString src s))
Nothing)
else normal_lit }
| otherwise = normal_lit
where
- normal_lit = do { liftCps (rnLit lit); return (LitPat (convertLit lit)) }
+ normal_lit = do { liftCps (rnLit lit); return (LitPat x (convertLit lit)) }
-rnPatAndThen _ (NPat (L l lit) mb_neg _eq _)
+rnPatAndThen _ (NPat x (L l lit) mb_neg _eq)
= do { (lit', mb_neg') <- liftCpsFV $ rnOverLit lit
; mb_neg' -- See Note [Negative zero]
<- let negative = do { (neg, fvs) <- lookupSyntaxName negateName
@@ -425,9 +431,9 @@ rnPatAndThen _ (NPat (L l lit) mb_neg _eq _)
(Nothing, Nothing) -> positive
(Just _ , Just _ ) -> positive
; eq' <- liftCpsFV $ lookupSyntaxName eqName
- ; return (NPat (L l lit') mb_neg' eq' placeHolderType) }
+ ; return (NPat x (L l lit') mb_neg' eq') }
-rnPatAndThen mk (NPlusKPat rdr (L l lit) _ _ _ _)
+rnPatAndThen mk (NPlusKPat x rdr (L l lit) _ _ _ )
= do { new_name <- newPatName mk rdr
; (lit', _) <- liftCpsFV $ rnOverLit lit -- See Note [Negative zero]
-- We skip negateName as
@@ -435,16 +441,16 @@ rnPatAndThen mk (NPlusKPat rdr (L l lit) _ _ _ _)
-- sense in n + k patterns
; minus <- liftCpsFV $ lookupSyntaxName minusName
; ge <- liftCpsFV $ lookupSyntaxName geName
- ; return (NPlusKPat (L (nameSrcSpan new_name) new_name)
- (L l lit') lit' ge minus placeHolderType) }
+ ; return (NPlusKPat x (L (nameSrcSpan new_name) new_name)
+ (L l lit') lit' ge minus) }
-- The Report says that n+k patterns must be in Integral
-rnPatAndThen mk (AsPat rdr pat)
+rnPatAndThen mk (AsPat x rdr pat)
= do { new_name <- newPatLName mk rdr
; pat' <- rnLPatAndThen mk pat
- ; return (AsPat new_name pat') }
+ ; return (AsPat x new_name pat') }
-rnPatAndThen mk p@(ViewPat expr pat _ty)
+rnPatAndThen mk p@(ViewPat x expr pat)
= do { liftCps $ do { vp_flag <- xoptM LangExt.ViewPatterns
; checkErr vp_flag (badViewPat p) }
-- Because of the way we're arranging the recursive calls,
@@ -453,45 +459,40 @@ rnPatAndThen mk p@(ViewPat expr pat _ty)
; pat' <- rnLPatAndThen mk pat
-- Note: at this point the PreTcType in ty can only be a placeHolder
-- ; return (ViewPat expr' pat' ty) }
- ; return (ViewPat expr' pat' placeHolderType) }
+ ; return (ViewPat x expr' pat') }
rnPatAndThen mk (ConPatIn con stuff)
-- rnConPatAndThen takes care of reconstructing the pattern
-- The pattern for the empty list needs to be replaced by an empty explicit list pattern when overloaded lists is turned on.
= case unLoc con == nameRdrName (dataConName nilDataCon) of
True -> do { ol_flag <- liftCps $ xoptM LangExt.OverloadedLists
- ; if ol_flag then rnPatAndThen mk (ListPat [] placeHolderType Nothing)
+ ; if ol_flag then rnPatAndThen mk (ListPat noExt [])
else rnConPatAndThen mk con stuff}
False -> rnConPatAndThen mk con stuff
-rnPatAndThen mk (ListPat pats _ _)
+rnPatAndThen mk (ListPat _ pats)
= do { opt_OverloadedLists <- liftCps $ xoptM LangExt.OverloadedLists
; pats' <- rnLPatsAndThen mk pats
; case opt_OverloadedLists of
True -> do { (to_list_name,_) <- liftCps $ lookupSyntaxName toListName
- ; return (ListPat pats' placeHolderType
- (Just (placeHolderType, to_list_name)))}
- False -> return (ListPat pats' placeHolderType Nothing) }
-
-rnPatAndThen mk (PArrPat pats _)
- = do { pats' <- rnLPatsAndThen mk pats
- ; return (PArrPat pats' placeHolderType) }
+ ; return (ListPat (Just to_list_name) pats')}
+ False -> return (ListPat Nothing pats') }
-rnPatAndThen mk (TuplePat pats boxed _)
+rnPatAndThen mk (TuplePat x pats boxed)
= do { liftCps $ checkTupSize (length pats)
; pats' <- rnLPatsAndThen mk pats
- ; return (TuplePat pats' boxed []) }
+ ; return (TuplePat x pats' boxed) }
-rnPatAndThen mk (SumPat pat alt arity _)
+rnPatAndThen mk (SumPat x pat alt arity)
= do { pat <- rnLPatAndThen mk pat
- ; return (SumPat pat alt arity PlaceHolder)
+ ; return (SumPat x pat alt arity)
}
-- If a splice has been run already, just rename the result.
-rnPatAndThen mk (SplicePat (HsSpliced mfs (HsSplicedPat pat)))
- = SplicePat . HsSpliced mfs . HsSplicedPat <$> rnPatAndThen mk pat
+rnPatAndThen mk (SplicePat x (HsSpliced x2 mfs (HsSplicedPat pat)))
+ = SplicePat x . HsSpliced x2 mfs . HsSplicedPat <$> rnPatAndThen mk pat
-rnPatAndThen mk (SplicePat splice)
+rnPatAndThen mk (SplicePat _ splice)
= do { eith <- liftCpsFV $ rnSplicePat splice
; case eith of -- See Note [rnSplicePat] in RnSplice
Left not_yet_renamed -> rnPatAndThen mk not_yet_renamed
@@ -534,7 +535,7 @@ rnHsRecPatsAndThen mk (L _ con) hs_rec_fields@(HsRecFields { rec_dotdot = dd })
; flds' <- mapM rn_field (flds `zip` [1..])
; return (HsRecFields { rec_flds = flds', rec_dotdot = dd }) }
where
- mkVarPat l n = VarPat (L l n)
+ mkVarPat l n = VarPat noExt (L l n)
rn_field (L l fld, n') = do { arg' <- rnLPatAndThen (nested_mk dd mk n')
(hsRecFieldArg fld)
; return (L l (fld { hsRecFieldArg = arg' })) }
@@ -568,7 +569,7 @@ rnHsRecFields
-- This surprisingly complicated pass
-- a) looks up the field name (possibly using disambiguation)
-- b) fills in puns and dot-dot stuff
--- When we we've finished, we've renamed the LHS, but not the RHS,
+-- When we've finished, we've renamed the LHS, but not the RHS,
-- of each x=e binding
--
-- This is used for record construction and pattern-matching, but not updates.
@@ -576,7 +577,7 @@ rnHsRecFields
rnHsRecFields ctxt mk_arg (HsRecFields { rec_flds = flds, rec_dotdot = dotdot })
= do { pun_ok <- xoptM LangExt.RecordPuns
; disambig_ok <- xoptM LangExt.DisambiguateRecordFields
- ; parent <- check_disambiguation disambig_ok mb_con
+ ; let parent = guard disambig_ok >> mb_con
; flds1 <- mapM (rn_fld pun_ok parent) flds
; mapM_ (addErr . dupFieldErr ctxt) dup_flds
; dotdot_flds <- rn_dotdot dotdot mb_con flds1
@@ -585,25 +586,17 @@ rnHsRecFields ctxt mk_arg (HsRecFields { rec_flds = flds, rec_dotdot = dotdot })
; return (all_flds, mkFVs (getFieldIds all_flds)) }
where
mb_con = case ctxt of
- HsRecFieldCon con | not (isUnboundName con) -> Just con
- HsRecFieldPat con | not (isUnboundName con) -> Just con
- _ {- update or isUnboundName con -} -> Nothing
- -- The unbound name test is because if the constructor
- -- isn't in scope the constructor lookup will add an error
- -- add an error, but still return an unbound name.
- -- We don't want that to screw up the dot-dot fill-in stuff.
-
- doc = case mb_con of
- Nothing -> text "constructor field name"
- Just con -> text "field of constructor" <+> quotes (ppr con)
+ HsRecFieldCon con -> Just con
+ HsRecFieldPat con -> Just con
+ _ {- update -} -> Nothing
rn_fld :: Bool -> Maybe Name -> LHsRecField GhcPs (Located arg)
-> RnM (LHsRecField GhcRn (Located arg))
rn_fld pun_ok parent (L l (HsRecField { hsRecFieldLbl
- = L loc (FieldOcc (L ll lbl) _)
+ = L loc (FieldOcc _ (L ll lbl))
, hsRecFieldArg = arg
, hsRecPun = pun }))
- = do { sel <- setSrcSpan loc $ lookupRecFieldOcc parent doc lbl
+ = do { sel <- setSrcSpan loc $ lookupRecFieldOcc parent lbl
; arg' <- if pun
then do { checkErr pun_ok (badPun (L loc lbl))
-- Discard any module qualifier (#11662)
@@ -611,20 +604,22 @@ rnHsRecFields ctxt mk_arg (HsRecFields { rec_flds = flds, rec_dotdot = dotdot })
; return (L loc (mk_arg loc arg_rdr)) }
else return arg
; return (L l (HsRecField { hsRecFieldLbl
- = L loc (FieldOcc (L ll lbl) sel)
+ = L loc (FieldOcc sel (L ll lbl))
, hsRecFieldArg = arg'
, hsRecPun = pun })) }
+ rn_fld _ _ (L _ (HsRecField (L _ (XFieldOcc _)) _ _))
+ = panic "rnHsRecFields"
rn_dotdot :: Maybe Int -- See Note [DotDot fields] in HsPat
-> Maybe Name -- The constructor (Nothing for an
-- out of scope constructor)
-> [LHsRecField GhcRn (Located arg)] -- Explicit fields
-> RnM [LHsRecField GhcRn (Located arg)] -- Filled in .. fields
- rn_dotdot Nothing _mb_con _flds -- No ".." at all
- = return []
- rn_dotdot (Just {}) Nothing _flds -- Constructor out of scope
- = return []
rn_dotdot (Just n) (Just con) flds -- ".." on record construction / pat match
+ | not (isUnboundName con) -- This test is because if the constructor
+ -- isn't in scope the constructor lookup will add
+ -- an error but still return an unbound name. We
+ -- don't want that to screw up the dot-dot fill-in stuff.
= ASSERT( flds `lengthIs` n )
do { loc <- getSrcSpanM -- Rather approximate
; dd_flag <- xoptM LangExt.RecordWildCards
@@ -654,64 +649,32 @@ rnHsRecFields ctxt mk_arg (HsRecFields { rec_flds = flds, rec_dotdot = dotdot })
; addUsedGREs dot_dot_gres
; return [ L loc (HsRecField
- { hsRecFieldLbl = L loc (FieldOcc (L loc arg_rdr) sel)
+ { hsRecFieldLbl = L loc (FieldOcc sel (L loc arg_rdr))
, hsRecFieldArg = L loc (mk_arg loc arg_rdr)
, hsRecPun = False })
| fl <- dot_dot_fields
, let sel = flSelector fl
, let arg_rdr = mkVarUnqual (flLabel fl) ] }
- check_disambiguation :: Bool -> Maybe Name -> RnM (Maybe Name)
- -- When disambiguation is on, return name of parent tycon.
- check_disambiguation disambig_ok mb_con
- | disambig_ok, Just con <- mb_con
- = do { env <- getGlobalRdrEnv; return (find_tycon env con) }
- | otherwise = return Nothing
-
- find_tycon :: GlobalRdrEnv -> Name {- DataCon -}
- -> Maybe Name {- TyCon -}
- -- Return the parent *type constructor* of the data constructor
- -- (that is, the parent of the data constructor),
- -- or 'Nothing' if it is a pattern synonym or not in scope.
- -- That's the parent to use for looking up record fields.
- find_tycon env con_name
- | Just (AConLike (RealDataCon dc)) <- wiredInNameTyThing_maybe con_name
- = Just (tyConName (dataConTyCon dc))
- -- Special case for [], which is built-in syntax
- -- and not in the GlobalRdrEnv (Trac #8448)
-
- | Just gre <- lookupGRE_Name env con_name
- = case gre_par gre of
- ParentIs p -> Just p
- _ -> Nothing -- Can happen if the con_name
- -- is for a pattern synonym
-
- | otherwise = Nothing
- -- Data constructor not lexically in scope at all
- -- See Note [Disambiguation and Template Haskell]
-
- dup_flds :: [[RdrName]]
+ rn_dotdot _dotdot _mb_con _flds
+ = return []
+ -- _dotdot = Nothing => No ".." at all
+ -- _mb_con = Nothing => Record update
+ -- _mb_con = Just unbound => Out of scope data constructor
+
+ 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
(_, dup_flds) = removeDups compare (getFieldLbls flds)
-{- Note [Disambiguation and Template Haskell]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Consider (Trac #12130)
- module Foo where
- import M
- b = $(funny)
-
- module M(funny) where
- data T = MkT { x :: Int }
- funny :: Q Exp
- funny = [| MkT { x = 3 } |]
-
-When we splice, neither T nor MkT are lexically in scope, so find_tycon will
-fail. But there is no need for disambiguation anyway, so we just return Nothing
--}
+-- NB: Consider this:
+-- module Foo where { data R = R { fld :: Int } }
+-- module Odd where { import Foo; fld x = x { fld = 3 } }
+-- Arguably this should work, because the reference to 'fld' is
+-- unambiguous because there is only one field id 'fld' in scope.
+-- But currently it's rejected.
rnHsRecUpdFields
:: [LHsRecUpdField GhcPs]
@@ -750,7 +713,7 @@ rnHsRecUpdFields flds
then do { checkErr pun_ok (badPun (L loc lbl))
-- Discard any module qualifier (#11662)
; let arg_rdr = mkRdrUnqual (rdrNameOcc lbl)
- ; return (L loc (HsVar (L loc arg_rdr))) }
+ ; return (L loc (HsVar noExt (L loc arg_rdr))) }
else return arg
; (arg'', fvs) <- rnLExpr arg'
@@ -760,16 +723,16 @@ rnHsRecUpdFields flds
Right _ -> fvs
lbl' = case sel of
Left sel_name ->
- L loc (Unambiguous (L loc lbl) sel_name)
+ L loc (Unambiguous sel_name (L loc lbl))
Right [sel_name] ->
- L loc (Unambiguous (L loc lbl) sel_name)
- Right _ -> L loc (Ambiguous (L loc lbl) PlaceHolder)
+ L loc (Unambiguous sel_name (L loc lbl))
+ Right _ -> L loc (Ambiguous noExt (L loc lbl))
; return (L l (HsRecField { hsRecFieldLbl = lbl'
, 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
@@ -784,7 +747,7 @@ getFieldLbls :: [LHsRecField id arg] -> [RdrName]
getFieldLbls flds
= map (unLoc . rdrNameFieldOcc . unLoc . hsRecFieldLbl . unLoc) flds
-getFieldUpdLbls :: [LHsRecUpdField id] -> [RdrName]
+getFieldUpdLbls :: [LHsRecUpdField GhcPs] -> [RdrName]
getFieldUpdLbls flds = map (rdrNameAmbiguousFieldOcc . unLoc . hsRecFieldLbl . unLoc) flds
needFlagDotDot :: HsRecFieldContext -> SDoc
@@ -803,10 +766,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
@@ -868,11 +831,10 @@ rnOverLit origLit
; (SyntaxExpr { syn_expr = from_thing_name }, fvs1)
<- lookupSyntaxName std_name
; let rebindable = case from_thing_name of
- HsVar (L _ v) -> v /= std_name
- _ -> panic "rnOverLit"
+ HsVar _ (L _ v) -> v /= std_name
+ _ -> panic "rnOverLit"
; let lit' = lit { ol_witness = from_thing_name
- , ol_rebindable = rebindable
- , ol_type = placeHolderType }
+ , ol_ext = rebindable }
; if isNegativeZeroOverLit lit'
then do { (SyntaxExpr { syn_expr = negate_name }, fvs2)
<- lookupSyntaxName negateName