diff --git a/compiler/GHC/Data/FastString.hs b/compiler/GHC/Data/FastString.hs index dcb6901b2c13875c160d6c6efec7d31b4542088a..36d6a2d820b89d949710cf156c84c1e520ed80b7 100644 --- a/compiler/GHC/Data/FastString.hs +++ b/compiler/GHC/Data/FastString.hs @@ -419,7 +419,8 @@ prototyping safe newtype-coercions: GHC.NT.Type.NT was imported, but could not be looked up /by the plugin/. let rdrName = mkModuleName "GHC.NT.Type" `mkRdrQual` mkTcOcc "NT" - putMsgS $ showSDoc dflags $ ppr $ lookupGRE_RdrName rdrName $ mg_rdr_env guts + putMsgS $ showSDoc dflags $ ppr $ + lookupGRE (mg_rdr_env guts) (LookupRdrName rdrName AllRelevantGREs) `mkTcOcc` involves the lookup (or creation) of a FastString. Since the plugin's FastString.string_table is empty, constructing the RdrName also diff --git a/compiler/GHC/Rename/Doc.hs b/compiler/GHC/Rename/Doc.hs index f8499cf8c8b8611a0eab973600342570c37ec4b7..f32f3ec7cc0cdaacc1033be39d9f89515da019ac 100644 --- a/compiler/GHC/Rename/Doc.hs +++ b/compiler/GHC/Rename/Doc.hs @@ -8,7 +8,6 @@ import GHC.Types.Name.Reader import GHC.Types.Name import GHC.Types.SrcLoc import GHC.Tc.Utils.Monad (getGblEnv) -import GHC.Rename.Env rnLHsDoc :: LHsDoc GhcPs -> RnM (LHsDoc GhcRn) rnLHsDoc = traverse rnHsDoc @@ -41,6 +40,5 @@ rnHsDocIdentifiers :: GlobalRdrEnv rnHsDocIdentifiers gre_env ns = [ L l $ greName gre | L l rdr_name <- ns - , gre <- lookupGRE_RdrName AllNameSpaces gre_env rdr_name - , rdrRelevantNameSpace rdr_name $ greNameSpace gre + , gre <- lookupGRE gre_env (LookupOccName (rdrNameOcc rdr_name) AllRelevantGREs) ] diff --git a/compiler/GHC/Rename/Env.hs b/compiler/GHC/Rename/Env.hs index ce4a4f458fe19495b29c59fb7fb88f4de84af0c2..e4d8a9d5553e613e2f89ed380015d42645947caf 100644 --- a/compiler/GHC/Rename/Env.hs +++ b/compiler/GHC/Rename/Env.hs @@ -33,7 +33,6 @@ module GHC.Rename.Env ( ChildLookupResult(..), lookupSubBndrOcc_helper, - childrenNameSpaces, -- Called by lookupChildrenExport HsSigCtxt(..), lookupLocalTcNames, lookupSigOccRn, lookupSigOccRnN, lookupSigCtxtOccRn, @@ -58,7 +57,6 @@ module GHC.Rename.Env ( addUsedGRE, addUsedGREs, addUsedDataCons, dataTcOccs, --TODO: Move this somewhere, into utils? - rdrRelevantNameSpace, ) where @@ -115,7 +113,7 @@ import Control.Arrow ( first ) import Control.Monad import Data.Either ( partitionEithers ) import Data.Function ( on ) -import Data.List ( find, partition, groupBy, sort, sortBy ) +import Data.List ( find, partition, groupBy, sortBy ) import Data.Foldable ( for_ ) import qualified Data.List.NonEmpty as NE import qualified Data.Semigroup as Semi @@ -298,7 +296,7 @@ lookupTopBndrRn which_suggest rdr_name = (do { op_ok <- xoptM LangExt.TypeOperators ; unless op_ok (addErr (TcRnIllegalTypeOperatorDecl rdr_name)) }) ; env <- getGlobalRdrEnv - ; case filter isLocalGRE (lookupGRE_RdrName (IncludeFields WantNormal False) env rdr_name) of + ; case filter isLocalGRE (lookupGRE env $ LookupRdrName rdr_name $ RelevantGREsFOS WantNormal) of [gre] -> return (greName gre) _ -> do -- Ambiguous (can't happen) or unbound traceRn "lookupTopBndrRN fail" (ppr rdr_name) @@ -357,14 +355,14 @@ lookupExternalExactName name lookupLocalExactGRE :: Name -> RnM (Either NotInScopeError GlobalRdrElt) lookupLocalExactGRE name = do { env <- getGlobalRdrEnv - ; let occ = nameOccName name - gres = [ gre | gre <- lookupGRE_OccName AllNameSpaces env occ - -- We're filtering by an exact 'Name' match, - -- so we should look up as many potential matches as possible. - -- See Note [rdrRelevantNameSpace and Exact Names] - -- and test cases T9066, T11809. - , greName gre == name ] - ; case gres of + ; let lk = LookupExactName { lookupExactName = name + , lookInAllNameSpaces = True } + -- We want to check for clashes where the same Unique + -- occurs in two different NameSpaces, as per + -- Note [Template Haskell ambiguity]. So we + -- check ALL namespaces, not just the NameSpace of the Name. + -- See test cases T9066, T11809. + ; case lookupGRE env lk of [gre] -> return (Right gre) [] -> -- See Note [Splicing Exact names] @@ -562,7 +560,7 @@ lookupRecFieldOcc mb_con rdr_name ; Just nm -> return nm } } | otherwise -- Can't use the data constructor to disambiguate - = lookupGlobalOccRn' (IncludeFields WantField False) rdr_name + = lookupGlobalOccRn' (RelevantGREsFOS WantField) rdr_name -- This use of Global is right as we are looking up a selector, -- which can only be defined at the top level. @@ -683,38 +681,20 @@ lookupGlobalOccRn will find it. -} -- | Used in export lists to lookup the children. -lookupSubBndrOcc_helper :: forall ns_prio - . Ord ns_prio - => Bool -> DeprecationWarnings +lookupSubBndrOcc_helper :: Bool -> DeprecationWarnings -> Name -> RdrName -- ^ thing we are looking up - -> (NameSpace -> Maybe ns_prio) + -> LookupChild -- ^ how to look it up (e.g. which + -- 'NameSpace's to look in) -> RnM ChildLookupResult -lookupSubBndrOcc_helper must_have_parent warn_if_deprec parent rdr_name ns_prio +lookupSubBndrOcc_helper must_have_parent warn_if_deprec parent rdr_name how_lkup | isUnboundName parent -- Avoid an error cascade = return (FoundChild (mkUnboundGRERdr rdr_name)) | otherwise = do gre_env <- getGlobalRdrEnv - - let gre_prio :: GlobalRdrElt -> Maybe (ns_prio, Int) - gre_prio gre = case ns_prio $ greNameSpace gre of - Nothing -> Nothing - Just np -> Just (np, case right_parent gre of { NoOccurrence -> 1 ; _ -> 0 }) - -- Prioritise GREs first on NameSpace, and then on Parent. - -- See T11970. - original_gres = - highestPriority gre_prio - $ lookupGRE_OccName AllNameSpaces gre_env (rdrNameOcc rdr_name) - -- Look in all NameSpaces: - -- - -- - we want to include fields defined with no field selectors, - -- as we can export those as children. See test NFSExport. - -- - for a variable, we might also need to look in the type/class namespace - -- see e.g. test T10816. - - -- Disambiguate the lookup based on the parent information. + let original_gres = lookupGRE gre_env (LookupChildren (rdrNameOcc rdr_name) how_lkup) -- The remaining GREs are things that we *could* export here, note that -- this includes things which have `NoParent`. Those are sorted in -- `checkPatSynParent`. @@ -786,46 +766,6 @@ lookupSubBndrOcc_helper must_have_parent warn_if_deprec parent rdr_name ns_prio NoParent -> UniqueOccurrence p {-# INLINEABLE lookupSubBndrOcc_helper #-} --- | Collect the 'GlobalRdrElt's with the highest priority 'NameSpace' according --- to the given function (lower value <=> higher priority). --- --- This allows us to first look in e.g. the data 'NameSpace', and then fall back --- to the type/class 'NameSpace'. -highestPriority :: Ord prio - => (GlobalRdrElt -> Maybe prio) - -- ^ priority function - -- lower value <=> higher priority - -> [GlobalRdrElt] -> [GlobalRdrElt] -highestPriority priority gres = - take_highest_prio $ NE.group $ sort - [ Semi.Arg prio gre - | gre <- gres - , prio <- maybeToList $ priority gre ] - where - take_highest_prio :: [NE.NonEmpty (Semi.Arg prio GlobalRdrElt)] -> [GlobalRdrElt] - take_highest_prio [] = [] - take_highest_prio (fs:_) = map (\ (Semi.Arg _ gre) -> gre) $ NE.toList fs -{-# INLINEABLE highestPriority #-} - --- | Pick out the possible 'NameSpace's in order of priority. --- This is a consequence of how the parser parses all --- data constructors as type constructors. -childrenNameSpaces :: NameSpace -> (NameSpace -> Maybe Int) -childrenNameSpaces ns other_ns - | other_ns == ns - = Just 0 - | isTermVarOrFieldNameSpace ns - , isTermVarOrFieldNameSpace other_ns - = Just 0 - | ns == varName - , other_ns == tcName - = Just 1 - | ns == tcName - , other_ns == dataName - = Just (-1) -- try data namespace before type/class namespace - | otherwise - = Nothing - -- This domain specific datatype is used to record why we decided it was -- possible that a GRE could be exported with a parent. data DisambigInfo @@ -897,7 +837,7 @@ lookupSubBndrOcc :: DeprecationWarnings lookupSubBndrOcc warn_if_deprec the_parent doc rdr_name = lookupExactOrOrig rdr_name (Right . greName) $ -- This happens for built-in classes, see mod052 for example - do { child <- lookupSubBndrOcc_helper True warn_if_deprec the_parent rdr_name relevant_ns + do { child <- lookupSubBndrOcc_helper True warn_if_deprec the_parent rdr_name what_lkup ; return $ case child of FoundChild g -> Right (greName g) NameNotFound -> Left (UnknownSubordinate doc) @@ -905,22 +845,8 @@ lookupSubBndrOcc warn_if_deprec the_parent doc rdr_name = -- See [Mismatched class methods and associated type families] -- in TcInstDecls. where - -- We already mostly know the exact NameSpace we want. The only exception - -- is that sometimes we are looking up a symbolic variable name and might - -- want the symbolic type constructor, e.g. for an infix declaration - -- "infix +!" we want to take into account both class methods and associated - -- types. See test T10816. - relevant_ns :: NameSpace -> Maybe Int - relevant_ns other_ns - | ns == other_ns - = Just 0 - | isVarNameSpace ns - , isTcClsNameSpace other_ns - = Just 1 - | otherwise - = Nothing - ns = rdrNameSpace rdr_name - + what_lkup = LookupChild { wantedParent = the_parent + , lookupDataConFirst = False } {- Note [Family instance binders] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1195,7 +1121,7 @@ lookup_demoted rdr_name -- ^^^^^^^^^^^ report_qualified_term_in_types :: RdrName -> RdrName -> RnM Name report_qualified_term_in_types rdr_name demoted_rdr_name = - do { mName <- lookupGlobalOccRn_maybe (IncludeFields WantNormal False) demoted_rdr_name + do { mName <- lookupGlobalOccRn_maybe (RelevantGREsFOS WantNormal) demoted_rdr_name ; case mName of (Just _) -> termNameInType looking_for rdr_name demoted_rdr_name [] Nothing -> unboundTermNameInTypes looking_for rdr_name demoted_rdr_name } @@ -1307,14 +1233,14 @@ lookupOccRnX_maybe globalLookup wrapper rdr_name lookupOccRn_maybe :: RdrName -> RnM (Maybe GlobalRdrElt) lookupOccRn_maybe = lookupOccRnX_maybe - (lookupGlobalOccRn_maybe $ IncludeFields WantNormal False) + (lookupGlobalOccRn_maybe $ RelevantGREsFOS WantNormal) return -- Used outside this module only by TH name reification (lookupName, lookupThName_maybe) lookupSameOccRn_maybe :: RdrName -> RnM (Maybe Name) lookupSameOccRn_maybe = lookupOccRnX_maybe - (get_name <$> lookupGlobalOccRn_maybe SameOccName) + (get_name <$> lookupGlobalOccRn_maybe SameNameSpace) (return . greName) where get_name :: RnM (Maybe GlobalRdrElt) -> RnM (Maybe Name) @@ -1364,7 +1290,7 @@ lookupGlobalOccRn :: RdrName -> RnM Name -- environment. -- -- Used by exports_from_avail -lookupGlobalOccRn = lookupGlobalOccRn' (IncludeFields WantNormal False) +lookupGlobalOccRn = lookupGlobalOccRn' (RelevantGREsFOS WantNormal) lookupGlobalOccRn' :: WhichGREs GREInfo -> RdrName -> RnM Name lookupGlobalOccRn' which_gres rdr_name = @@ -1374,10 +1300,10 @@ lookupGlobalOccRn' which_gres rdr_name = Just gre -> return (greName gre) Nothing -> do { traceRn "lookupGlobalOccRn" (ppr rdr_name) ; unboundName (LF which_suggest WL_Global) rdr_name } - where which_suggest = case which_gres of - IncludeFields WantBoth _ -> WL_RecField - IncludeFields WantField _ -> WL_RecField - _ -> WL_Anything + where which_suggest = case includeFieldSelectors which_gres of + WantBoth -> WL_RecField + WantField -> WL_RecField + WantNormal -> WL_Anything -- Looks up a RdrName occurrence in the GlobalRdrEnv and with -- lookupQualifiedNameGHCi. Does not try to find an Exact or Orig name first. @@ -1392,9 +1318,10 @@ lookupGlobalOccRn_base which_gres rdr_name = -- and only happens for failed lookups where fos = case which_gres of - IncludeFields f_or_s _ -> f_or_s - AllNameSpaces -> WantBoth - _ -> WantNormal + RelevantGREs { includeFieldSelectors = sel } -> sel + _ -> if isFieldOcc (rdrNameOcc rdr_name) + then WantField + else WantNormal -- | Lookup a 'Name' in the 'GlobalRdrEnv', falling back to looking up -- in the type environment it if fails. @@ -1420,7 +1347,7 @@ lookupInfoOccRn :: RdrName -> RnM [Name] lookupInfoOccRn rdr_name = lookupExactOrOrig rdr_name (\ gre -> [greName gre]) $ do { rdr_env <- getGlobalRdrEnv - ; let nms = map greName $ lookupGRE_RdrName (IncludeFields WantBoth False) rdr_env rdr_name + ; let nms = map greName $ lookupGRE rdr_env (LookupRdrName rdr_name (RelevantGREsFOS WantBoth)) ; qual_nms <- map greName <$> lookupQualifiedNameGHCi WantBoth rdr_name ; return $ nms ++ (qual_nms `minusList` nms) } @@ -1437,7 +1364,7 @@ lookupFieldGREs env (L loc rdr) $ do { res <- lookupExactOrOrig rdr (\ gre -> maybeToList $ fieldGRE_maybe gre) $ do { let (env_fld_gres, env_var_gres) = partition isRecFldGRE $ - lookupGRE_RdrName (IncludeFields WantBoth False) env rdr + lookupGRE env (LookupRdrName rdr (RelevantGREsFOS WantBoth)) -- Handle implicit qualified imports in GHCi. See T10439. ; ghci_gres <- lookupQualifiedNameGHCi WantBoth rdr @@ -1474,7 +1401,7 @@ lookupFieldGREs env (L loc rdr) lookupGlobalOccRn_overloaded :: RdrName -> RnM (Maybe GlobalRdrElt) lookupGlobalOccRn_overloaded rdr_name = lookupExactOrOrig_maybe rdr_name id $ - do { res <- lookupGreRn_helper (IncludeFields WantNormal False) rdr_name AllDeprecationWarnings + do { res <- lookupGreRn_helper (RelevantGREsFOS WantNormal) rdr_name AllDeprecationWarnings ; case res of GreNotFound -> lookupOneQualifiedNameGHCi WantNormal rdr_name OneNameMatch gre -> return $ Just gre @@ -1733,7 +1660,7 @@ is enabled then we defer the selection until the typechecker. lookupGreRn_helper :: WhichGREs GREInfo -> RdrName -> DeprecationWarnings -> RnM GreLookupResult lookupGreRn_helper which_gres rdr_name warn_if_deprec = do { env <- getGlobalRdrEnv - ; case lookupGRE_RdrName which_gres env rdr_name of + ; case lookupGRE env (LookupRdrName rdr_name which_gres) of [] -> return GreNotFound [gre] -> do { addUsedGRE warn_if_deprec gre ; return (OneNameMatch gre) } @@ -1747,7 +1674,7 @@ lookupGreAvailRn :: RdrName -> RnM (Maybe GlobalRdrElt) -- Uses addUsedRdrName to record use and deprecations lookupGreAvailRn rdr_name = do - mb_gre <- lookupGreRn_helper (IncludeFields WantNormal False) rdr_name ExportDeprecationWarnings + mb_gre <- lookupGreRn_helper (RelevantGREsFOS WantNormal) rdr_name ExportDeprecationWarnings case mb_gre of GreNotFound -> do @@ -1992,10 +1919,7 @@ lookupOneQualifiedNameGHCi fos rdr_name = do -- | Look up *all* the names to which the 'RdrName' may refer in GHCi (using -- @-fimplicit-import-qualified@). This will normally be zero or one, but may -- be more in the presence of @DuplicateRecordFields@. -lookupQualifiedNameGHCi :: HasDebugCallStack - => FieldsOrSelectors - -> RdrName -- ^ the 'RdrName' to look up - -> RnM [GlobalRdrElt] +lookupQualifiedNameGHCi :: HasDebugCallStack => FieldsOrSelectors -> RdrName -> RnM [GlobalRdrElt] lookupQualifiedNameGHCi fos rdr_name = -- We want to behave as we would for a source file import here, -- and respect hiddenness of modules/packages, hence loadSrcInterface. @@ -2165,14 +2089,8 @@ lookupSigCtxtOccRn :: HsSigCtxt -> RnM (GenLocated (SrcSpanAnn' ann) Name) lookupSigCtxtOccRn ctxt what = wrapLocMA $ \ rdr_name -> - do { let ns = rdrNameSpace rdr_name - -- For a term variable, also look in record field NameSpaces. - relevant_ns - | isTermVarOrFieldNameSpace ns - = isTermVarOrFieldNameSpace - | otherwise - = (== ns) - ; mb_names <- lookupBindGroupOcc ctxt what rdr_name relevant_ns + do { let also_try_tycons = False + ; mb_names <- lookupBindGroupOcc ctxt what rdr_name also_try_tycons ; case mb_names of Right name NE.:| rest -> do { massertPpr (null rest) $ @@ -2185,25 +2103,27 @@ lookupSigCtxtOccRn ctxt what lookupBindGroupOcc :: HsSigCtxt -> SDoc - -> RdrName - -> (NameSpace -> Bool) + -> RdrName -- ^ what to look up + -> Bool -- ^ if the 'RdrName' we are looking up is in + -- a value 'NameSpace', should we also look up + -- in the type constructor 'NameSpace'? -> RnM (NE.NonEmpty (Either NotInScopeError Name)) --- Looks up the RdrName, expecting it to resolve to one of the --- bound names passed in. If not, return an appropriate error message +-- ^ Looks up the 'RdrName', expecting it to resolve to one of the +-- bound names currently in scope. If not, return an appropriate error message. -- --- See Note [Looking up signature names] -lookupBindGroupOcc ctxt what rdr_name ok_ns +-- See Note [Looking up signature names]. +lookupBindGroupOcc ctxt what rdr_name also_try_tycon_ns | Just n <- isExact_maybe rdr_name - = do { mb_nm <- fmap greName <$> lookupExactOcc_either n - ; return $ case mb_nm of - Left err -> NE.singleton $ Left err - Right n' -> finish (NoExactName n') n' } + = do { mb_gre <- lookupExactOcc_either n + ; return $ case mb_gre of + Left err -> NE.singleton $ Left err + Right gre -> finish (NoExactName $ greName gre) gre } -- Maybe we should check the side conditions -- but it's a pain, and Exact things only show -- up when you know what you are doing | Just (rdr_mod, rdr_occ) <- isOrig_maybe rdr_name - = do { finish NotInScope <$> lookupOrig rdr_mod rdr_occ } + = do { NE.singleton . Right <$> lookupOrig rdr_mod rdr_occ } | otherwise = case ctxt of @@ -2217,9 +2137,18 @@ lookupBindGroupOcc ctxt what rdr_name ok_ns else lookup_top (`elemNameSet` ns) where - finish err n - | ok_ns (nameNameSpace n) - = NE.singleton (Right n) + ns = occNameSpace occ + occ = rdrNameOcc rdr_name + relevant_gres = + RelevantGREs + { includeFieldSelectors = WantBoth + , lookupVariablesForFields = True + , lookupTyConsAsWell = also_try_tycon_ns } + ok_gre = greIsRelevant relevant_gres ns + + finish err gre + | ok_gre gre + = NE.singleton (Right $ greName gre) | otherwise = NE.singleton (Left err) @@ -2230,14 +2159,13 @@ lookupBindGroupOcc ctxt what rdr_name ok_ns lookup_top keep_me = do { env <- getGlobalRdrEnv - ; let all_gres = filter (ok_ns . greNameSpace) - $ lookupGRE_OccName AllNameSpaces env (rdrNameOcc rdr_name) + ; let occ = rdrNameOcc rdr_name + all_gres = lookupGRE env (LookupOccName occ relevant_gres) names_in_scope = -- If rdr_name lacks a binding, only -- recommend alternatives from relevant -- namespaces. See #17593. - filter (ok_ns . nameNameSpace) - $ map greName - $ filter isLocalGRE + map greName + $ filter (ok_gre <&&> isLocalGRE) $ globalRdrEnvElts env candidates_msg = candidates names_in_scope ; case filter (keep_me . greName) all_gres of @@ -2269,8 +2197,8 @@ lookupBindGroupOcc ctxt what rdr_name ok_ns where similar_names = fuzzyLookup (unpackFS $ occNameFS $ rdrNameOcc rdr_name) - $ map (\x -> ((unpackFS $ occNameFS $ nameOccName x), x)) - names_in_scope + $ map (\x -> ((unpackFS $ occNameFS $ nameOccName x), x)) + names_in_scope --------------- @@ -2281,8 +2209,9 @@ lookupLocalTcNames :: HsSigCtxt -> SDoc -> RdrName -> RnM [(RdrName, Name)] -- See Note [Fixity signature lookup] lookupLocalTcNames ctxt what rdr = do { this_mod <- getModule + ; let also_try_tycon_ns = True ; nms_eithers <- fmap (guard_builtin_syntax this_mod rdr) <$> - lookupBindGroupOcc ctxt what rdr (rdrRelevantNameSpace rdr) + lookupBindGroupOcc ctxt what rdr also_try_tycon_ns ; let (errs, names) = partitionEithers (NE.toList nms_eithers) ; when (null names) $ addErr (head errs) -- Bleat about one only @@ -2301,7 +2230,7 @@ lookupLocalTcNames ctxt what rdr dataTcOccs :: RdrName -> [RdrName] -- Return both the given name and the same name promoted to the TcClsName -- namespace. This is useful when we aren't sure which we are looking at. --- See also Note [rdrRelevantNameSpace and Exact Names] +-- See also Note [dataTcOccs and Exact Names] dataTcOccs rdr_name | isDataOcc occ || isVarOcc occ = [rdr_name, rdr_name_tc] @@ -2311,31 +2240,8 @@ dataTcOccs rdr_name occ = rdrNameOcc rdr_name rdr_name_tc = setRdrNameSpace rdr_name tcName --- | Which 'NameSpace's should we consult when looking up this 'RdrName'? --- --- For data constructor and term variable 'NameSpace's, also look in the TyCon --- 'NameSpace', as explained in Note [rdrRelevantNameSpace and Exact Names]. --- --- For term variables, also look in the record field 'NameSpace's. -rdrRelevantNameSpace :: RdrName -> NameSpace -> Bool --- Return both the given name and the same name promoted to the TcClsName --- namespace. This is useful when we aren't sure which we are looking at. --- See also Note [rdrRelevantNameSpace and Exact Names] -rdrRelevantNameSpace rdr_name - | isDataOcc occ - = isDataConNameSpace <||> isTcClsNameSpace - | isVarOcc occ - = isTermVarOrFieldNameSpace <||> isTcClsNameSpace - | isFieldOcc occ - = isVarNameSpace <||> (== ns) - | otherwise - = (== ns) - where - occ = rdrNameOcc rdr_name - ns = occNameSpace occ - -{- Note [rdrRelevantNameSpace and Exact Names] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +{- Note [dataTcOccs and Exact Names] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Exact RdrNames can occur in code generated by Template Haskell, and generally those references are, well, exact. However, the TH `Name` type isn't expressive enough to always track the correct namespace information, so we sometimes get @@ -2346,6 +2252,9 @@ There is also an awkward situation for built-in syntax. Example in GHCi :info [] This parses as the Exact RdrName for nilDataCon, but we also want the list type constructor. + +Note that setRdrNameSpace on an Exact name requires the Name to be External, +which it always is for built in syntax. -} {- diff --git a/compiler/GHC/Rename/HsType.hs b/compiler/GHC/Rename/HsType.hs index 103fae04d03cff859e68377d896c2aa8c09ea2b2..39d9f21f14c72aec291a22a927c48688137859b6 100644 --- a/compiler/GHC/Rename/HsType.hs +++ b/compiler/GHC/Rename/HsType.hs @@ -1143,7 +1143,7 @@ warn_term_var_capture lVar = do case demoteRdrNameTv $ unLoc lVar of Nothing -> return () Just demoted_name -> do - let global_vars = lookupGRE_RdrName SameOccName gbl_env demoted_name + let global_vars = lookupGRE gbl_env (LookupRdrName demoted_name SameNameSpace) let mlocal_var = lookupLocalRdrEnv local_env demoted_name case mlocal_var of Just name -> warnCapturedTerm lVar (Right name) diff --git a/compiler/GHC/Rename/Names.hs b/compiler/GHC/Rename/Names.hs index 2baddb0646d1dcf1d207b324af7ecd677761abd4..bfb1862743ba8b9b96d36004f3ceed5fa4334906 100644 --- a/compiler/GHC/Rename/Names.hs +++ b/compiler/GHC/Rename/Names.hs @@ -730,7 +730,7 @@ extendGlobalRdrEnvRn new_gres new_fixities where -- See Note [Reporting duplicate local declarations] dups = filter isBadDupGRE - $ lookupGRE_OccName (IncludeFields WantBoth True) env (greOccName gre) + $ lookupGRE env (LookupOccName (greOccName gre) (RelevantGREsFOS WantBoth)) isBadDupGRE old_gre = isLocalGRE old_gre && greClashesWith gre old_gre {- Note [Fail fast on duplicate definitions] @@ -927,7 +927,7 @@ getLocalNonValBinders fixity_env -- See (1) above L loc cls_rdr <- MaybeT $ pure $ getLHsInstDeclClass_maybe inst_ty -- See (2) above - MaybeT $ setSrcSpan (locA loc) $ lookupGlobalOccRn_maybe SameOccName cls_rdr + MaybeT $ setSrcSpan (locA loc) $ lookupGlobalOccRn_maybe SameNameSpace cls_rdr -- Assuming the previous step succeeded, process any associated data -- family instances. If the previous step failed, bail out. case mb_cls_gre of diff --git a/compiler/GHC/Rename/Unbound.hs b/compiler/GHC/Rename/Unbound.hs index 0f8c83930923932b01a38ff18031ec8dfde8b73d..8c1b580ad150d2c7d86c202d9e3d621a215712c3 100644 --- a/compiler/GHC/Rename/Unbound.hs +++ b/compiler/GHC/Rename/Unbound.hs @@ -212,7 +212,7 @@ fieldSelectorSuggestions global_env tried_rdr_name | otherwise = [RemindFieldSelectorSuppressed tried_rdr_name parents] where gres = filter isNoFieldSelectorGRE - $ lookupGRE_RdrName (IncludeFields WantField False) global_env tried_rdr_name + $ lookupGRE global_env (LookupRdrName tried_rdr_name AllRelevantGREs) parents = [ parent | ParentIs parent <- map greParent gres ] similarNameSuggestions :: LookingFor -> DynFlags @@ -355,7 +355,8 @@ importSuggestions looking_for global_env hpt currMod imports rdr_name helpful_imports = filter helpful interesting_imports where helpful (_,imv) = any (isGreOk looking_for) $ - lookupGRE_OccName (IncludeFields WantNormal True) (imv_all_exports imv) occ_name + lookupGRE (imv_all_exports imv) + (LookupOccName occ_name $ RelevantGREsFOS WantNormal) -- Which of these do that because of an explicit hiding list resp. an -- explicit import list diff --git a/compiler/GHC/Rename/Utils.hs b/compiler/GHC/Rename/Utils.hs index f9856522e8405a5b2288bc89b49a50f69c393b7e..9cf7af183af9211ea2fc703e4bda436bbe739c08 100644 --- a/compiler/GHC/Rename/Utils.hs +++ b/compiler/GHC/Rename/Utils.hs @@ -164,7 +164,7 @@ checkShadowedOccs (global_env,local_env) get_loc_occ ns where (loc,occ) = get_loc_occ n mb_local = lookupLocalRdrOcc local_env occ - gres = lookupGRE_RdrName (IncludeFields WantBoth True) global_env (mkRdrUnqual occ) + gres = lookupGRE global_env (LookupRdrName (mkRdrUnqual occ) (RelevantGREsFOS WantBoth)) -- Make an Unqualified RdrName and look that up, so that -- we don't find any GREs that are in scope qualified-only diff --git a/compiler/GHC/Runtime/Loader.hs b/compiler/GHC/Runtime/Loader.hs index a2ab8a69ac69e086cccd051c2e9227ea5fd7629b..ed9226089416f119395d9872ea33fe16becebeaf 100644 --- a/compiler/GHC/Runtime/Loader.hs +++ b/compiler/GHC/Runtime/Loader.hs @@ -362,7 +362,7 @@ lookupRdrNameInModuleForPlugins hsc_env mod_name rdr_name = do imp_spec = ImpSpec decl_spec ImpAll env = mkGlobalRdrEnv $ gresFromAvails hsc_env (Just imp_spec) (mi_exports iface) - case lookupGRE_RdrName (IncludeFields WantNormal False) env rdr_name of + case lookupGRE env (LookupRdrName rdr_name (RelevantGREsFOS WantNormal)) of [gre] -> return (Just (greName gre, iface)) [] -> return Nothing _ -> panic "lookupRdrNameInModule" diff --git a/compiler/GHC/Tc/Errors.hs b/compiler/GHC/Tc/Errors.hs index 5537523e234c8e1996a9ce36db1a898fff8c7adb..420c93edfe691b13cb4af684c0484331d3f2522a 100644 --- a/compiler/GHC/Tc/Errors.hs +++ b/compiler/GHC/Tc/Errors.hs @@ -2384,7 +2384,7 @@ mk_dict_err ctxt (item, (matches, unifiers, unsafe_overlapped)) = case (NE.nonEm | otherwise = [] occ_name_in_scope glb_env lcl_env occ_name = not $ - null (lookupGRE_OccName (IncludeFields WantNormal False) glb_env occ_name) && + null (lookupGRE glb_env (LookupOccName occ_name (RelevantGREsFOS WantNormal))) && isNothing (lookupLocalRdrOcc lcl_env occ_name) record_field = case orig of diff --git a/compiler/GHC/Tc/Gen/Export.hs b/compiler/GHC/Tc/Gen/Export.hs index ff7fef606a6ffaa58bf422dfd80d65dd3b9894ac..3912b95c7f8a746166619a17dd8f531dfa5df8ec 100644 --- a/compiler/GHC/Tc/Gen/Export.hs +++ b/compiler/GHC/Tc/Gen/Export.hs @@ -689,9 +689,13 @@ lookupChildrenExport spec_parent rdr_items = mapAndReportM doOne rdr_items doOne n = do let bareName = (ieWrappedName . unLoc) n + what_lkup :: LookupChild + what_lkup = LookupChild { wantedParent = spec_parent + , lookupDataConFirst = True } + -- Do not report export list declaration deprecations name <- lookupSubBndrOcc_helper False ExportDeprecationWarnings - spec_parent bareName (childrenNameSpaces $ rdrNameSpace bareName) + spec_parent bareName what_lkup traceRn "lookupChildrenExport" (ppr name) -- Default to data constructors for slightly better error -- messages diff --git a/compiler/GHC/Tc/Module.hs b/compiler/GHC/Tc/Module.hs index b8ae990474510453fbdc7d6e94dc810adca657be..5293a86371994b514da370709701ea2afe37d9cb 100644 --- a/compiler/GHC/Tc/Module.hs +++ b/compiler/GHC/Tc/Module.hs @@ -958,9 +958,10 @@ checkHiBootIface' = Just (gre, Nothing) matching_flds | isVarOcc missing_occ -- (This only applies to variables.) - = lookupGRE_OccName (IncludeFields WantField False) gre_env missing_occ + = lookupGRE gre_env $ + LookupOccName missing_occ (RelevantGREsFOS WantField) | otherwise - = [] + = [] -- BootFldReexport T18999_NoDisambiguateRecordFields T16745A in case mapMaybe mb_ok $ matching_flds of @@ -1750,7 +1751,7 @@ checkMainType tcg_env do { rdr_env <- getGlobalRdrEnv ; let dflags = hsc_dflags hsc_env main_occ = getMainOcc dflags - main_gres = lookupGRE_OccName SameOccName rdr_env main_occ + main_gres = lookupGRE rdr_env (LookupOccName main_occ SameNameSpace) ; case filter isLocalGRE main_gres of { [] -> return emptyWC ; (_:_:_) -> return emptyWC ; diff --git a/compiler/GHC/Tc/Utils/Backpack.hs b/compiler/GHC/Tc/Utils/Backpack.hs index bd17ee0699c7fe5fdf17d8e2539d3414c05207f4..0e93253fabe66d26c7ff3e0313286bed797775d9 100644 --- a/compiler/GHC/Tc/Utils/Backpack.hs +++ b/compiler/GHC/Tc/Utils/Backpack.hs @@ -160,7 +160,7 @@ checkHsigIface tcg_env gre_env sig_iface -- The hsig did NOT define this function; that means it must -- be a reexport. In this case, make sure the 'Name' of the -- reexport matches the 'Name' exported here. - | [gre] <- lookupGRE_OccName (IncludeFields WantNormal True) gre_env (nameOccName name) = do + | [gre] <- lookupGRE gre_env (LookupOccName (nameOccName name) SameNameSpace) = do let name' = greName gre when (name /= name') $ do -- See Note [Error reporting bad reexport] @@ -741,7 +741,7 @@ mergeSignatures -- STEP 4.1: Merge fixities (we'll verify shortly) tcg_fix_env let fix_env = mkNameEnv [ (greName rdr_elt, FixItem occ f) | (occ, f) <- concatMap mi_fixities ifaces - , rdr_elt <- lookupGRE_OccName (IncludeFields WantBoth True) rdr_env occ ] + , rdr_elt <- lookupGRE rdr_env (LookupOccName occ AllRelevantGREs) ] -- STEP 5: Typecheck the interfaces let type_env_var = tcg_type_env_var tcg_env @@ -955,7 +955,7 @@ checkImplements impl_mod req_mod@(Module uid mod_name) = do impl_iface False{- safe -} NotBoot ImportedBySystem fix_env = mkNameEnv [ (greName rdr_elt, FixItem occ f) | (occ, f) <- mi_fixities impl_iface - , rdr_elt <- lookupGRE_OccName (IncludeFields WantBoth True) impl_gr occ ] + , rdr_elt <- lookupGRE impl_gr (LookupOccName occ AllRelevantGREs) ] updGblEnv (\tcg_env -> tcg_env { -- Setting tcg_rdr_env to treat all exported entities from -- the implementing module as in scope improves error messages, @@ -989,7 +989,7 @@ checkImplements impl_mod req_mod@(Module uid mod_name) = do -- STEP 3: Check that the implementing interface exports everything -- we need. (Notice we IGNORE the Modules in the AvailInfos.) forM_ (exportOccs (mi_exports isig_iface)) $ \occ -> - case lookupGRE_OccName SameOccName impl_gr occ of + case lookupGRE impl_gr (LookupOccName occ SameNameSpace) of [] -> addErr $ TcRnHsigMissingModuleExport occ unit_state impl_mod _ -> return () failIfErrsM diff --git a/compiler/GHC/ThToHs.hs b/compiler/GHC/ThToHs.hs index 812aa2ea89cb63f352290c37634c6f0e25eaae85..119cd695c2e265929b3759b676dc7046da8b96aa 100644 --- a/compiler/GHC/ThToHs.hs +++ b/compiler/GHC/ThToHs.hs @@ -31,7 +31,6 @@ where import GHC.Prelude hiding (init, last, tail) import GHC.Hs as Hs -import GHC.Builtin.Names import GHC.Tc.Errors.Types import GHC.Types.Name.Reader import qualified GHC.Types.Name as Name diff --git a/compiler/GHC/Types/Name/Ppr.hs b/compiler/GHC/Types/Name/Ppr.hs index 6ab771a9e02ad64afe7c599d00a4d776d249fbc3..3e6ca84acb71ae8124434afc1e60edaf8a84ac24 100644 --- a/compiler/GHC/Types/Name/Ppr.hs +++ b/compiler/GHC/Types/Name/Ppr.hs @@ -97,7 +97,8 @@ mkQualName env = qual_name where = NameQual (greQualModName gre) | null qual_gres - = if null (lookupGRE_RdrName SameOccName env (mkRdrQual (moduleName mod) occ)) + = if null $ lookupGRE env $ + LookupRdrName (mkRdrQual (moduleName mod) occ) SameNameSpace then NameNotInScope1 else NameNotInScope2 @@ -127,8 +128,8 @@ mkQualName env = qual_name where right_name gre = greDefinitionModule gre == Just mod - unqual_gres = lookupGRE_RdrName SameOccName env (mkRdrUnqual occ) - qual_gres = filter right_name (lookupGRE_OccName SameOccName env occ) + unqual_gres = lookupGRE env (LookupRdrName (mkRdrUnqual occ) SameNameSpace) + qual_gres = filter right_name (lookupGRE env (LookupOccName occ SameNameSpace)) -- we can mention a module P:M without the P: qualifier iff -- "import M" would resolve unambiguously to P:M. (if P is the @@ -150,7 +151,7 @@ mkPromTick ptc env = ptcListTuplePuns ptc | Just occ' <- promoteOccName occ - , [] <- lookupGRE_RdrName SameOccName env (mkRdrUnqual occ') + , [] <- lookupGRE env (LookupRdrName (mkRdrUnqual occ') SameNameSpace) = -- Could not find a corresponding type name in the environment, -- so the data name is unambiguous. Promotion tick not needed. False diff --git a/compiler/GHC/Types/Name/Reader.hs b/compiler/GHC/Types/Name/Reader.hs index e2ef8f18a214c6d043d1798a9bc2fc10796f1caa..6f2db7435617082984a488b19cde8a2805c20e9a 100644 --- a/compiler/GHC/Types/Name/Reader.hs +++ b/compiler/GHC/Types/Name/Reader.hs @@ -7,6 +7,8 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE PatternSynonyms #-} -- | -- #name_types# @@ -53,7 +55,13 @@ module GHC.Types.Name.Reader ( -- ** Looking up 'GlobalRdrElt's FieldsOrSelectors(..), filterFieldGREs, allowGRE, - WhichGREs(..), lookupGRE_OccName, lookupGRE_RdrName, lookupGRE_Name, + + LookupGRE(..), lookupGRE, + WhichGREs(.., AllRelevantGREs, RelevantGREsFOS), + greIsRelevant, + LookupChild(..), + + lookupGRE_Name, lookupGRE_FieldLabel, getGRE_NameQualifier_maybes, transformGREs, pickGREs, pickGREsModExp, @@ -127,6 +135,7 @@ import GHC.Utils.Panic import Control.DeepSeq import Control.Monad ( guard ) import Data.Data +import Data.List ( sort ) import qualified Data.List.NonEmpty as NE import qualified Data.Map.Strict as Map import qualified Data.Semigroup as S @@ -584,8 +593,8 @@ absence of the 'GREInfo' field. This parametrisation also helps ensure that we don't accidentally force the GREInfo field (which can cause unnecessary loading of interface files). -In particular, the 'lookupGRE_OccName' is statically guaranteed to not consult -the 'GREInfo' field when its first argument is 'SameOccName', which is important +In particular, the 'lookupGRE' function is statically guaranteed to not consult +the 'GREInfo' field when using 'SameNameSpace', which is important as we sometimes need to use this function with an 'IfaceGlobalRdrEnv' in which the 'GREInfo' fields have been stripped. -} @@ -1061,7 +1070,7 @@ data FieldsOrSelectors -- they have selectors). | WantField -- ^ Include only fields, with or without selectors, ignoring -- any non-fields in scope. - deriving Eq + deriving (Eq, Show) filterFieldGREs :: FieldsOrSelectors -> [GlobalRdrElt] -> [GlobalRdrElt] filterFieldGREs WantBoth = id @@ -1082,7 +1091,7 @@ allowGRE WantNormal gre allowGRE WantField gre = isRecFldGRE gre --- | How should we look up in a 'GlobalRdrEnv'? Should we only look up +-- | What should we look up in a 'GlobalRdrEnv'? Should we only look up -- names with the exact same 'OccName', or do we allow different 'NameSpace's? -- -- Depending on the answer, we might need more or less information from the @@ -1091,72 +1100,245 @@ allowGRE WantField gre -- we need to consult the 'GREInfo'. This is why this datatype is a GADT. -- -- See Note [IfGlobalRdrEnv]. -data WhichGREs info where +data LookupGRE info where -- | Look for this specific 'OccName', with the exact same 'NameSpace', -- in the 'GlobalRdrEnv'. - SameOccName :: WhichGREs info - -- | Look for variables in record field namespaces, and look for - -- record fields in variable namespaces, depending on the arguments. - IncludeFields :: FieldsOrSelectors - -- ^ How should we handle variables? - -- - -- - Should we include record fields defined with @-XNoFieldSelectors@? - -- - Should we include non-fields? - -- - -- See Note [NoFieldSelectors]. - -> Bool - -- ^ For fields, should we also look up variables? - -> WhichGREs GREInfo - -- | Look up in all 'NameSpace's. - AllNameSpaces :: WhichGREs info - --- | Look for this 'OccName' in the global environment. --- --- The 'WhichGREs' argument specifies which 'GlobalRdrElt's we are interested in. -lookupGRE_OccName :: WhichGREs info -> GlobalRdrEnvX info -> OccName -> [GlobalRdrEltX info] -lookupGRE_OccName what env occ - | AllNameSpaces <- what - = concat $ lookupOccEnv_AllNameSpaces env occ - -- If the 'RdrName' is a variable, we might also need - -- to look up in the record field namespaces. - | isVarOcc occ - , Just flds <- mb_flds - = normal ++ flds - -- If the 'RdrName' is a record field, we might want to check - -- the variable namespace too. - | isFieldOcc occ - , Just flds <- mb_flds - = flds ++ case what of { IncludeFields _ True -> vars; _ -> [] } + LookupOccName :: OccName -- ^ the 'OccName' to look up + -> WhichGREs info + -- ^ information about other relevant 'NameSpace's + -> LookupGRE info + + -- | Look up the 'OccName' of this 'RdrName' in the 'GlobalRdrEnv', + -- filtering out those whose qualification matches that of the 'RdrName'. + -- + -- Lookup returns an empty result for 'Exact' or 'Orig' 'RdrName's. + LookupRdrName :: RdrName -- ^ the 'RdrName' to look up + -> WhichGREs info + -- ^ information about other relevant 'NameSpace's + -> LookupGRE info + + -- | Look for 'GRE's with the same unique as the given 'Name' + -- in the 'GlobalRdrEnv'. + LookupExactName + :: { lookupExactName :: Name + -- ^ the 'Name' to look up + , lookInAllNameSpaces :: Bool + -- ^ whether to look in *all* 'NameSpace's, or just + -- in the 'NameSpace' of the 'Name' + -- See Note [Template Haskell ambiguity] + } + -> LookupGRE info + + -- | Look up children 'GlobalRdrElt's with a given 'Parent'. + LookupChildren + :: OccName -- ^ the 'OccName' to look up + -> LookupChild + -- ^ information to decide which 'GlobalRdrElt's + -- are valid children after looking up + -> LookupGRE info + +-- | How should we look up in a 'GlobalRdrEnv'? +-- Which 'NameSpace's are considered relevant for a given lookup? +data WhichGREs info where + -- | Only consider 'GlobalRdrElt's with the exact 'NameSpace' we look up. + SameNameSpace :: WhichGREs info + -- | Allow 'GlobalRdrElt's with different 'NameSpace's, e.g. allow looking up + -- record fields from the variable 'NameSpace', or looking up a 'TyCon' from + -- the data constructor 'NameSpace'. + RelevantGREs + :: { includeFieldSelectors :: !FieldsOrSelectors + -- ^ how should we handle looking up variables? + -- + -- - should we include record fields defined with @-XNoFieldSelectors@? + -- - should we include non-fields? + -- + -- See Note [NoFieldSelectors]. + , lookupVariablesForFields :: !Bool + -- ^ when looking up a record field, should we also look up plain variables? + , lookupTyConsAsWell :: !Bool + -- ^ when looking up a variable, field or data constructor, should we + -- also try the type constructor 'NameSpace'? + } + -> WhichGREs GREInfo + +-- | Look up as many possibly relevant 'GlobalRdrElt's as possible. +pattern AllRelevantGREs :: WhichGREs GREInfo +pattern AllRelevantGREs = + RelevantGREs { includeFieldSelectors = WantBoth + , lookupVariablesForFields = True + , lookupTyConsAsWell = True } + +-- | Look up relevant GREs, taking into account the interaction between the +-- variable and field 'NameSpace's as determined by the 'FieldsOrSelector' +-- argument. +pattern RelevantGREsFOS :: FieldsOrSelectors -> WhichGREs GREInfo +pattern RelevantGREsFOS fos <- RelevantGREs { includeFieldSelectors = fos } + where + RelevantGREsFOS fos = + RelevantGREs { includeFieldSelectors = fos + , lookupVariablesForFields = fos == WantBoth + , lookupTyConsAsWell = False } + +data LookupChild + = LookupChild + { wantedParent :: Name + -- ^ the parent we are looking up children of + , lookupDataConFirst :: Bool + -- ^ for type constructors, should we look in the data constructor + -- namespace first? + } + +-- | After looking up something with the given 'NameSpace', is the resulting +-- 'GlobalRdrElt' we have obtained relevant, according to the 'RelevantGREs' +-- specification of which 'NameSpace's are relevant? +greIsRelevant :: WhichGREs GREInfo -- ^ specification of which 'GlobalRdrElt's to consider relevant + -> NameSpace -- ^ the 'NameSpace' of the thing we are looking up + -> GlobalRdrElt -- ^ the 'GlobalRdrElt' we have looked up, in a + -- potentially different 'NameSpace' than we wanted + -> Bool +greIsRelevant which_gres ns gre + | ns == other_ns + = True | otherwise - = normal + = case which_gres of + SameNameSpace -> False + RelevantGREs { includeFieldSelectors = fos + , lookupVariablesForFields = vars_for_flds + , lookupTyConsAsWell = tycons_too } + | ns == varName + -> (isFieldNameSpace other_ns && allowGRE fos gre) || tc_too + | isFieldNameSpace ns + -> vars_for_flds && + ( other_ns == varName + || (isFieldNameSpace other_ns && allowGRE fos gre) + || tc_too ) + | isDataConNameSpace ns + -> tc_too + | otherwise + -> False + where + tc_too = tycons_too && isTcClsNameSpace other_ns + where + other_ns = greNameSpace gre + +-- | Scoring priority function for looking up children 'GlobalRdrElt'. +-- +-- First we score by 'NameSpace', with higher-priority 'NameSpace's having a +-- lower number. Then we break ties by checking if the 'Parent' is correct. +-- +-- This complicated scoring function is determined by the behaviour required by +-- 'lookupChildrenExport', which requires us to look in the data constructor +-- 'NameSpace' first, for things in the type constructor 'NameSpace'. +childGREPriority :: LookupChild -- ^ what kind of child do we want, + -- e.g. what should its parent be? + -> NameSpace -- ^ what 'NameSpace' are we originally looking in? + -> GlobalRdrEltX info + -- ^ the result of looking up; it might be in a different + -- 'NameSpace', which is used to determine the score + -- (in the first component) + -> Maybe (Int, Int) +childGREPriority (LookupChild { wantedParent = wanted_parent, lookupDataConFirst = try_dc_first }) + ns gre = + case child_ns_prio $ greNameSpace gre of + Nothing -> Nothing + Just np -> Just (np, parent_prio $ greParent gre) + -- Prioritise GREs first on NameSpace, and then on Parent. + -- See T11970. where - mb_flds = - case what of - IncludeFields fos _ -> Just $ filterFieldGREs fos $ concat $ lookupFieldsOccEnv env (occNameFS occ) - _ -> Nothing + -- Pick out the possible 'NameSpace's in order of priority. + child_ns_prio :: (NameSpace -> Maybe Int) + child_ns_prio other_ns + | other_ns == ns + = Just 0 + | isTermVarOrFieldNameSpace ns + , isTermVarOrFieldNameSpace other_ns + = Just 0 + | ns == varName + , other_ns == tcName + -- When looking up children, we sometimes want to a symbolic variable + -- name to resolve to a type constructor, e.g. for an infix declaration + -- "infix +!" we want to take into account both class methods and associated + -- types. See test T10816. + = Just 1 + | ns == tcName + , other_ns == dataName + , try_dc_first -- try data namespace before type/class namespace? + = Just (-1) + | otherwise + = Nothing + + parent_prio :: Parent -> Int + parent_prio (ParentIs other_parent) + | other_parent == wanted_parent = 0 + | otherwise = 1 + parent_prio NoParent = 0 - normal = fromMaybe [] $ lookupOccEnv env occ - vars = fromMaybe [] $ lookupOccEnv env (recFieldToVarOcc occ) +-- | Look something up in the Global Reader Environment. +-- +-- The 'LookupGRE' argument specifies what to look up, and in particular +-- whether there should there be any lee-way if the 'NameSpace's don't +-- exactly match. +lookupGRE :: GlobalRdrEnvX info -> LookupGRE info -> [GlobalRdrEltX info] +lookupGRE env = \case + LookupOccName occ which_gres -> + case which_gres of + SameNameSpace -> + concat $ lookupOccEnv env occ + rel@(RelevantGREs{}) -> + filter (greIsRelevant rel (occNameSpace occ)) $ + concat $ lookupOccEnv_AllNameSpaces env occ + LookupRdrName rdr rel -> + pickGREs rdr $ lookupGRE env (LookupOccName (rdrNameOcc rdr) rel) + LookupExactName { lookupExactName = nm + , lookInAllNameSpaces = all_ns } -> + [ gre | gre <- lkup, greName gre == nm ] + where + occ = nameOccName nm + lkup | all_ns = concat $ lookupOccEnv_AllNameSpaces env occ + | otherwise = fromMaybe [] $ lookupOccEnv env occ + LookupChildren occ which_child -> + highestPriorityGREs (childGREPriority which_child ns) $ + concat $ lookupOccEnv_AllNameSpaces env occ + where + ns :: NameSpace + ns = occNameSpace occ --- | Like 'lookupGRE_OccName', but for a 'RdrName'. -lookupGRE_RdrName :: WhichGREs info -> GlobalRdrEnvX info -> RdrName -> [GlobalRdrEltX info] -lookupGRE_RdrName what env rdr = - pickGREs rdr $ lookupGRE_OccName what env (rdrNameOcc rdr) +-- | Collect the 'GlobalRdrElt's with the highest priority according +-- to the given function (lower value <=> higher priority). +-- +-- This allows us to first look in e.g. the data 'NameSpace', and then fall back +-- to the type/class 'NameSpace'. +highestPriorityGREs :: forall info prio + . Ord prio + => (GlobalRdrEltX info -> Maybe prio) + -- ^ priority function + -- lower value <=> higher priority + -> [GlobalRdrEltX info] -> [GlobalRdrEltX info] +highestPriorityGREs priority gres = + take_highest_prio $ NE.group $ sort + [ S.Arg prio gre + | gre <- gres + , prio <- maybeToList $ priority gre ] + where + take_highest_prio :: [NE.NonEmpty (S.Arg prio (GlobalRdrEltX info))] -> [GlobalRdrEltX info] + take_highest_prio [] = [] + take_highest_prio (fs:_) = map (\ (S.Arg _ gre) -> gre) $ NE.toList fs +{-# INLINEABLE highestPriorityGREs #-} --- | Look for precisely this 'Name' in the environment. +-- | Look for precisely this 'Name' in the environment, +-- in the __same 'NameSpace'__ as the 'Name'. -- -- This tests whether it is in scope, ignoring anything -- else that might be in scope which doesn't have the same 'Unique'. lookupGRE_Name :: Outputable info => GlobalRdrEnvX info -> Name -> Maybe (GlobalRdrEltX info) lookupGRE_Name env name = - let occ = nameOccName name - in case [ gre | gre <- lookupGRE_OccName SameOccName env occ - , gre_name gre == name ] of + case lookupGRE env (LookupExactName { lookupExactName = name + , lookInAllNameSpaces = False }) of [] -> Nothing [gre] -> Just gre gres -> pprPanic "lookupGRE_Name" - (ppr name $$ ppr occ $$ ppr gres) + (ppr name $$ ppr (nameOccName name) $$ ppr gres) -- See INVARIANT 1 on GlobalRdrEnv -- | Look for a particular record field selector in the environment. @@ -1542,16 +1724,17 @@ greIsShadowed old_gre shadowed = -- | Whether a 'GlobalRdrElt' is definitely shadowed, definitely not shadowed, -- or conditionally shadowed based on more information beyond the 'NameSpace'. data IsShadowed + -- | The GRE is not shadowed. = IsNotShadowed + -- | The GRE is shadowed. | IsShadowed + -- | The GRE is shadowed iff it is a record field GRE + -- which defines a field selector (i.e. FieldSelectors is enabled in its + -- defining module). | IsShadowedIfFieldSelector -- | Internal function: is a 'GlobalRdrElt' with the 'NameSpace' with given -- 'Unique' shadowed by the specified 'ShadowedGREs'? --- --- - @Just b@ means: definitely @b@. --- - @Nothing@ means: the GRE is shadowed iff it is a record field GRE --- with FieldSelectors enabled. namespace_is_shadowed :: Unique -> ShadowedGREs -> IsShadowed namespace_is_shadowed old_ns (ShadowedGREs shadowed_nonflds shadowed_flds) | isFldNSUnique old_ns diff --git a/testsuite/tests/overloadedrecflds/should_compile/BootFldReexport.stderr b/testsuite/tests/overloadedrecflds/should_compile/BootFldReexport.stderr index b284812ce29302ae59f643eb7cf6b47c6b55aa09..f0b47db0f5ae3912dae2bd478f9cf1d9c2fa3f8a 100644 --- a/testsuite/tests/overloadedrecflds/should_compile/BootFldReexport.stderr +++ b/testsuite/tests/overloadedrecflds/should_compile/BootFldReexport.stderr @@ -2,10 +2,10 @@ BootFldReexport.hs:8:9: error: [GHC-87543] Ambiguous occurrence ‘fld’. It could refer to - either ‘BootFldReexport_N.fld’, + either the field ‘fld’ of record ‘BootFldReexport_O.O’, + imported from ‘BootFldReexport_O’ at BootFldReexport.hs:6:5-7 + (and originally defined at BootFldReexport_O.hs:5:16-18), + or ‘BootFldReexport_N.fld’, imported from ‘BootFldReexport_N’ at BootFldReexport.hs:4:5-7 (and originally defined in ‘BootFldReexport_O’ - at BootFldReexport_O.hs-boot:4:1-13), - or the field ‘fld’ of record ‘BootFldReexport_O.O’, - imported from ‘BootFldReexport_O’ at BootFldReexport.hs:6:5-7 - (and originally defined at BootFldReexport_O.hs:5:16-18). + at BootFldReexport_O.hs-boot:4:1-13). diff --git a/testsuite/tests/overloadedrecflds/should_fail/T16745.stderr b/testsuite/tests/overloadedrecflds/should_fail/T16745.stderr index ebc974a123b6964f53789a7bae394c9447ff0c1a..39d1d6d71a4a494309a1715582ed34f28fd064a3 100644 --- a/testsuite/tests/overloadedrecflds/should_fail/T16745.stderr +++ b/testsuite/tests/overloadedrecflds/should_fail/T16745.stderr @@ -6,9 +6,9 @@ T16745A.hs:8:9: error: [GHC-87543] Ambiguous occurrence ‘field’. It could refer to - either ‘T16745B.field’, + either the field ‘field’ of record ‘T16745B.R’, imported from ‘T16745B’ at T16745A.hs:3:24-28 - (and originally defined in ‘T16745C’ at T16745C.hs:2:1-5), - or the field ‘field’ of record ‘T16745B.R’, + (and originally defined at T16745B.hs:11:14-18), + or ‘T16745B.field’, imported from ‘T16745B’ at T16745A.hs:3:24-28 - (and originally defined at T16745B.hs:11:14-18). + (and originally defined in ‘T16745C’ at T16745C.hs:2:1-5). diff --git a/testsuite/tests/overloadedrecflds/should_fail/T18999_NoDisambiguateRecordFields.stderr b/testsuite/tests/overloadedrecflds/should_fail/T18999_NoDisambiguateRecordFields.stderr index a54338cbf0eb6a897b5baacfa5d052c9c4847f7e..6831c7c36573cc5c936ed4304e8b93709edc7dc8 100644 --- a/testsuite/tests/overloadedrecflds/should_fail/T18999_NoDisambiguateRecordFields.stderr +++ b/testsuite/tests/overloadedrecflds/should_fail/T18999_NoDisambiguateRecordFields.stderr @@ -2,11 +2,11 @@ T18999_NoDisambiguateRecordFields.hs:6:13: error: [GHC-87543] Ambiguous occurrence ‘not’. It could refer to - either ‘Prelude.not’, + either the field ‘not’ of record ‘Foo’, + defined at T18999_NoDisambiguateRecordFields.hs:4:18, + or ‘Prelude.not’, imported from ‘Prelude’ at T18999_NoDisambiguateRecordFields.hs:2:8-40 - (and originally defined in ‘GHC.Classes’), - or the field ‘not’ of record ‘Foo’, - defined at T18999_NoDisambiguateRecordFields.hs:4:18. + (and originally defined in ‘GHC.Classes’). T18999_NoDisambiguateRecordFields.hs:8:11: error: [GHC-56428] Ambiguous record field ‘not’.