summaryrefslogtreecommitdiff
path: root/compiler/rename/RnNames.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rename/RnNames.hs')
-rw-r--r--compiler/rename/RnNames.hs101
1 files changed, 68 insertions, 33 deletions
diff --git a/compiler/rename/RnNames.hs b/compiler/rename/RnNames.hs
index 2fc62637e8..2434bd9cce 100644
--- a/compiler/rename/RnNames.hs
+++ b/compiler/rename/RnNames.hs
@@ -4,7 +4,7 @@
\section[RnNames]{Extracting imported and top-level names in scope}
-}
-{-# LANGUAGE CPP, NondecreasingIndentation #-}
+{-# LANGUAGE CPP, NondecreasingIndentation, MultiWayIf, NamedFieldPuns #-}
module RnNames (
rnImports, getLocalNonValBinders, newRecordSelector,
@@ -12,7 +12,8 @@ module RnNames (
gresFromAvails,
calculateAvails,
reportUnusedNames,
- checkConName
+ checkConName,
+ exportItemErr
) where
#include "HsVersions.h"
@@ -49,6 +50,7 @@ import PatSyn
import qualified GHC.LanguageExtensions as LangExt
import Control.Monad
+import Data.Foldable (asum)
import Data.Either ( partitionEithers, isRight, rights )
-- import qualified Data.Foldable as Foldable
import Data.Map ( Map )
@@ -996,7 +998,7 @@ plusAvail a1 a2 = pprPanic "RnEnv.plusAvail" (hsep [ppr a1,ppr a2])
-- | trims an 'AvailInfo' to keep only a single name
trimAvail :: AvailInfo -> Name -> AvailInfo
-trimAvail (Avail b n) _ = Avail b n
+trimAvail (Avail n) _ = Avail n
trimAvail (AvailTC n ns fs) m = case find ((== m) . flSelector) fs of
Just x -> AvailTC n [] [x]
Nothing -> ASSERT( m `elem` ns ) AvailTC n [m] []
@@ -1009,7 +1011,7 @@ filterAvails keep avails = foldr (filterAvail keep) [] avails
filterAvail :: (Name -> Bool) -> AvailInfo -> [AvailInfo] -> [AvailInfo]
filterAvail keep ie rest =
case ie of
- Avail _ n | keep n -> ie : rest
+ Avail n | keep n -> ie : rest
| otherwise -> rest
AvailTC tc ns fs ->
let ns' = filter keep ns
@@ -1053,14 +1055,6 @@ mkChildEnv gres = foldr add emptyNameEnv gres
FldParent p _ -> extendNameEnv_Acc (:) singleton env p gre
ParentIs p -> extendNameEnv_Acc (:) singleton env p gre
NoParent -> env
- PatternSynonym -> env
-
-findPatSyns :: [GlobalRdrElt] -> [GlobalRdrElt]
-findPatSyns gres = foldr add [] gres
- where
- add g@(GRE { gre_par = PatternSynonym }) ps =
- g:ps
- add _ ps = ps
findChildren :: NameEnv [a] -> Name -> [a]
findChildren env n = lookupNameEnv env n `orElse` []
@@ -1088,6 +1082,58 @@ lookupChildren all_kids rdr_items
[(either (occNameFS . nameOccName) flLabel x, [x]) | x <- all_kids]
+-- This is a minefield. Three different things can appear in exports list.
+-- 1. Record selectors
+-- 2. Type constructors
+-- 3. Data constructors
+--
+-- However, things get put into weird name spaces.
+-- 1. Some type constructors are parsed as variables (-.->) for example.
+-- 2. All data constructors are parsed as type constructors
+-- 3. When there is ambiguity, we default type constructors to data
+-- constructors and require the explicit `type` keyword for type
+-- constructors.
+--
+--
+-- Further to this madness, duplicate record fields complicate
+-- things as we must find the FieldLabel rather than just the Name.
+--
+lookupChildrenExport :: Name -> [Located RdrName]
+ -> RnM ([Located Name], [Located FieldLabel])
+lookupChildrenExport parent rdr_items =
+ do
+ let
+
+ doOne :: Located RdrName
+ -> RnM (Either (Located Name) [Located FieldLabel])
+ doOne n = do
+
+ let bareName = unLoc n
+ lkup = lookupExportChild parent
+
+ mname <- runMaybeT . asum . map (MaybeT . lkup) $
+ [ (setRdrNameSpace bareName varName) -- Record selector
+ , (setRdrNameSpace bareName dataName) -- data constructor
+ , (setRdrNameSpace bareName tcName) -- type constructor
+ ]
+
+ -- Default to data constructors for slightly better error
+ -- messages
+ let unboundName :: RdrName
+ unboundName = if rdrNameSpace bareName == varName
+ then bareName
+ else setRdrNameSpace bareName dataName
+
+
+ name <- maybe (Left <$> reportUnboundName unboundName) return mname
+
+ case name of
+ Right fls -> return $ Right (map (L (getLoc n)) fls)
+ Left name -> return $ Left (L (getLoc n) name)
+
+ xs <- mapM doOne rdr_items
+ return $ (fmap concat . partitionEithers) xs
+
classifyGREs :: [GlobalRdrElt] -> ([Name], [FieldLabel])
classifyGREs = partitionEithers . map classifyGRE
@@ -1219,6 +1265,7 @@ rnExports explicit_mod exports
Just _ -> rn_exports,
tcg_dus = tcg_dus tcg_env `plusDU`
usesOnly final_ns })
+ ; failIfErrsM
; return (rn_exports, new_tcg_env) }
exports_from_avail :: Maybe (Located [LIE RdrName])
@@ -1260,8 +1307,6 @@ exports_from_avail (Just (L _ rdr_items)) rdr_env imports this_mod
kids_env :: NameEnv [GlobalRdrElt]
kids_env = mkChildEnv (globalRdrEnvElts rdr_env)
- pat_syns :: [GlobalRdrElt]
- pat_syns = findPatSyns (globalRdrEnvElts rdr_env)
imported_modules = [ imv_name imv
| xs <- moduleEnvElts $ imp_mods imports, imv <- xs ]
@@ -1339,13 +1384,13 @@ exports_from_avail (Just (L _ rdr_items)) rdr_env imports this_mod
lookup_ie ie@(IEThingWith l wc sub_rdrs _)
= do
- (lname, subs, avails, flds) <- lookup_ie_with ie l sub_rdrs
+ (lname, subs, avails, flds) <- lookup_ie_with l sub_rdrs
(_, all_avail, all_flds) <-
case wc of
NoIEWildcard -> return (lname, [], [])
IEWildcard _ -> lookup_ie_all ie l
let name = unLoc lname
- return (IEThingWith lname wc subs [],
+ return (IEThingWith lname wc subs (map noLoc (flds ++ all_flds)),
AvailTC name (name : avails ++ all_avail)
(flds ++ all_flds))
@@ -1354,26 +1399,16 @@ exports_from_avail (Just (L _ rdr_items)) rdr_env imports this_mod
lookup_ie _ = panic "lookup_ie" -- Other cases covered earlier
- lookup_ie_with :: IE RdrName -> Located RdrName -> [Located RdrName]
+ lookup_ie_with :: Located RdrName -> [Located RdrName]
-> RnM (Located Name, [Located Name], [Name], [FieldLabel])
- lookup_ie_with ie (L l rdr) sub_rdrs
+ lookup_ie_with (L l rdr) sub_rdrs
= do name <- lookupGlobalOccRn rdr
- let gres = findChildren kids_env name
- mchildren =
- lookupChildren (map classifyGRE (gres ++ pat_syns)) sub_rdrs
- addUsedKids rdr gres
+ (non_flds, flds) <- lookupChildrenExport name sub_rdrs
if isUnboundName name
then return (L l name, [], [name], [])
- else
- case mchildren of
- Nothing -> do
- addErr (exportItemErr ie)
- return (L l name, [], [name], [])
- Just (non_flds, flds) -> do
- addUsedKids rdr gres
- return (L l name, non_flds
- , map unLoc non_flds
- , map unLoc flds)
+ else return (L l name, non_flds
+ , map unLoc non_flds
+ , map unLoc flds)
lookup_ie_all :: IE RdrName -> Located RdrName
-> RnM (Located Name, [Name], [FieldLabel])
lookup_ie_all ie (L l rdr) =
@@ -1811,7 +1846,7 @@ printMinimalImports imports_w_usage
-- The main trick here is that if we're importing all the constructors
-- we want to say "T(..)", but if we're importing only a subset we want
-- to say "T(A,B,C)". So we have to find out what the module exports.
- to_ie _ (Avail _ n)
+ to_ie _ (Avail n)
= [IEVar (noLoc n)]
to_ie _ (AvailTC n [m] [])
| n==m = [IEThingAbs (noLoc n)]