Commit 9b73cb16 authored by Simon Peyton Jones's avatar Simon Peyton Jones

Refactor the GlobalRdrEnv, fixing #7672

This patch started innocently enough, by deleting a single
call from rnImportDecl, namely

    let gbl_env = mkGlobalRdrEnv (filterOut from_this_mod gres)

The 'filterOut' makes no sense, and was the cause of #7672.

But that little loose end led to into a twisty maze of little
passages, all alike, which has taken me an unreasonably long
time to straighten out. Happily, I think the result is really
much better.

In particular:

 * INVARIANT 1 of the GlobalRdrEnv type was simply not true:
   we had multiple GlobalRdrElts in a list with the same
   gre_name field. This kludgily implmented one form of
   shadowing.

 * Meanwhile, extendGlobalRdrEnvRn implemented a second form of
   shadowing, by deleting stuff from the GlobalRdrEnv.

 * In turn, much of this shadowing stuff depended on the Names of
   the Ids bound in the GHCi InteractiveContext being Internal
   names, even though the TyCons and suchlike all had External
   Names. Very confusing.

So I have made the following changes

 * I re-established INVARIANT 1 of GlobalRdrEnv.  As a result
   some strange code in RdrName.pickGREs goes away.

 * RnNames.extendGlobalRdrEnvRn now makes one call to deal with
   shadowing, where necessary, and another to extend the
   environment.  It deals separately with duplicate bindings.

   The very complicated RdrName.extendGlobalRdrEnv becomes much
   simpler; we need to export the shadowing function, now called
   RdrName.shadowNames; and we can nuke
   RdrName.findLocalDupsRdrEnv altogether.

   RdrName Note [GlobalRdrEnv shadowing] summarises the shadowing
   story

 * The Names of the Ids bound in the GHCi interactive context are
   now all External.  See Note [Interactively-bound Ids in GHCi]
   in HscTypes.

 * Names for Ids created by the debugger are now made by
   IfaceEnv.newInteractiveBinder.  This fixes a lurking bug which
   was that the debugger was using mkNewUniqueSupply 'I' to make
   uniques, which does NOT guarantee a fresh supply of uniques on
   successive calls.

 * Note [Template Haskell ambiguity] in RnEnv shows that one TH-related
   error is reported lazily (on occurrences) when it might be better
   reported when extending the environment.  In some (but not all) cases
   this was done before; but now it's uniformly at occurrences.  In
   some ways it'd be better to report when extending the environment,
   but it's a tiresome test and the error is rare, so I'm leaving it
   at the lookup site for now, with the above Note.

 * A small thing: RnNames.greAvail becomes RdrName.availFromGRE, where
   it joins the dual RdrName.gresFromAvail.
parent 11d8f84f
......@@ -44,13 +44,13 @@ module RdrName (
-- * Global mapping of 'RdrName' to 'GlobalRdrElt's
GlobalRdrEnv, emptyGlobalRdrEnv, mkGlobalRdrEnv, plusGlobalRdrEnv,
lookupGlobalRdrEnv, extendGlobalRdrEnv,
lookupGlobalRdrEnv, extendGlobalRdrEnv, shadowNames,
pprGlobalRdrEnv, globalRdrEnvElts,
lookupGRE_RdrName, lookupGRE_Name, getGRE_NameQualifier_maybes,
transformGREs, findLocalDupsRdrEnv, pickGREs,
transformGREs, pickGREs,
-- * GlobalRdrElts
gresFromAvails, gresFromAvail,
gresFromAvails, gresFromAvail, localGREsFromAvail, availFromGRE,
-- ** Global 'RdrName' mapping elements: 'GlobalRdrElt', 'Provenance', 'ImportSpec'
GlobalRdrElt(..), isLocalGRE, unQualOK, qualSpecOK, unQualSpecOK,
......@@ -400,14 +400,14 @@ type GlobalRdrEnv = OccEnv [GlobalRdrElt]
-- The list in the codomain is required because there may be name clashes
-- These only get reported on lookup, not on construction
--
-- INVARIANT: All the members of the list have distinct
-- 'gre_name' fields; that is, no duplicate Names
-- INVARIANT 1: All the members of the list have distinct
-- 'gre_name' fields; that is, no duplicate Names
--
-- INVARIANT: Imported provenance => Name is an ExternalName
-- However LocalDefs can have an InternalName. This
-- happens only when type-checking a [d| ... |] Template
-- Haskell quotation; see this note in RnNames
-- Note [Top-level Names in Template Haskell decl quotes]
-- INVARIANT 2: Imported provenance => Name is an ExternalName
-- However LocalDefs can have an InternalName. This
-- happens only when type-checking a [d| ... |] Template
-- Haskell quotation; see this note in RnNames
-- Note [Top-level Names in Template Haskell decl quotes]
-- | An element of the 'GlobalRdrEnv'
data GlobalRdrElt
......@@ -473,7 +473,7 @@ So: in an export list
Module M exports everything, so its exports will be
AvailTC C [C,T,op]
AvailTC T [T,TInt,TBool]
On import we convert to GlobalRdrElt and the combine
On import we convert to GlobalRdrElt and then combine
those. For T that will mean we have
one GRE with Parent C
one GRE with NoParent
......@@ -493,13 +493,25 @@ gresFromAvail prov_fn avail
gre_par = mkParent n avail,
gre_prov = prov_fn n}
| n <- availNames avail ]
where
localGREsFromAvail :: AvailInfo -> [GlobalRdrElt]
-- Turn an Avail into a list of LocalDef GlobalRdrElts
localGREsFromAvail = gresFromAvail (const LocalDef)
mkParent :: Name -> AvailInfo -> Parent
mkParent _ (Avail _) = NoParent
mkParent n (AvailTC m _) | n == m = NoParent
| otherwise = ParentIs m
availFromGRE :: GlobalRdrElt -> AvailInfo
availFromGRE gre
= case gre_par gre of
ParentIs p -> AvailTC p [me]
NoParent | isTyConName me -> AvailTC me [me]
| otherwise -> Avail me
where
me = gre_name gre
emptyGlobalRdrEnv :: GlobalRdrEnv
emptyGlobalRdrEnv = emptyOccEnv
......@@ -583,20 +595,9 @@ pickGREs :: RdrName -> [GlobalRdrElt] -> [GlobalRdrElt]
-- the locally-defined @f@, and a GRE for the imported @f@, with a /single/
-- provenance, namely the one for @Baz(f)@.
pickGREs rdr_name gres
| (_ : _ : _) <- candidates -- This is usually false, so we don't have to
-- even look at internal_candidates
, (gre : _) <- internal_candidates
= [gre] -- For this internal_candidate stuff,
-- see Note [Template Haskell binders in the GlobalRdrEnv]
-- If there are multiple Internal candidates, pick the
-- first one (ie with the (innermost binding)
| otherwise
= ASSERT2( isSrcRdrName rdr_name, ppr rdr_name )
candidates
mapMaybe pick gres
where
candidates = mapMaybe pick gres
internal_candidates = filter (isInternalName . gre_name) candidates
rdr_is_unqual = isUnqual rdr_name
rdr_is_qual = isQual_maybe rdr_name
......@@ -664,45 +665,62 @@ transformGREs trans_gre occs rdr_env
Just gres -> extendOccEnv env occ (map trans_gre gres)
Nothing -> env
extendGlobalRdrEnv :: Bool -> GlobalRdrEnv -> [AvailInfo] -> GlobalRdrEnv
-- Extend with new LocalDef GREs from the AvailInfos.
--
-- If do_shadowing is True, first remove name clashes between the new
-- AvailInfos and the existing GlobalRdrEnv.
-- This is used by the GHCi top-level
--
-- E.g. Adding a LocalDef "x" when there is an existing GRE for Q.x
-- should remove any unqualified import of Q.x,
-- leaving only the qualified one
--
-- However do *not* remove name clashes between the AvailInfos themselves,
-- so that (say) data T = A | A
-- will still give a duplicate-binding error.
-- Same thing if there are multiple AvailInfos (don't remove clashes),
-- though I'm not sure this ever happens with do_shadowing=True
extendGlobalRdrEnv do_shadowing env avails
= foldl add_avail env1 avails
where
names = concatMap availNames avails
env1 | do_shadowing = foldl shadow_name env names
| otherwise = env
-- By doing the removal first, we ensure that the new AvailInfos
-- don't shadow each other; that would conceal genuine errors
-- E.g. in GHCi data T = A | A
add_avail env avail = foldl (add_name avail) env (availNames avail)
add_name avail env name
= extendOccEnv_Acc (:) singleton env occ gre
where
occ = nameOccName name
gre = GRE { gre_name = name
, gre_par = mkParent name avail
, gre_prov = LocalDef }
extendGlobalRdrEnv :: GlobalRdrEnv -> GlobalRdrElt -> GlobalRdrEnv
extendGlobalRdrEnv env gre
= extendOccEnv_Acc insertGRE singleton env
(nameOccName (gre_name gre)) gre
shadowNames :: GlobalRdrEnv -> [Name] -> GlobalRdrEnv
shadowNames = foldl shadowName
{- Note [GlobalRdrEnv shadowing]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Before adding new names to the GlobalRdrEnv we nuke some existing entries;
this is "shadowing". The actual work is done by RdrEnv.shadowNames.
There are two reasons for shadowing:
* The GHCi REPL
- Ids bought into scope on the command line (eg let x = True) have
External Names, like Ghci4.x. We want a new binding for 'x' (say)
to override the existing binding for 'x'.
See Note [Interactively-bound Ids in GHCi] in HscTypes
- Data types also have Extenal Names, like Ghci4.T; but we still want
'T' to mean the newly-declared 'T', not an old one.
* Nested Template Haskell declaration brackets
See Note [Top-level Names in Template Haskell decl quotes] in RnNames
Consider a TH decl quote:
module M where
f x = h [d| f = 3 |]
We must shadow the outer declaration of 'f', else we'll get a
complaint when extending the GlobalRdrEnv, saying that there are two
bindings for 'f'. There are several tricky points:
- This shadowing applies even if the binding for 'f' is in a
where-clause, and hence is in the *local* RdrEnv not the *global*
RdrEnv. This is done in lcl_env_TH in extendGlobalRdrEnvRn.
- The External Name M.f from the enclosing module must certainly
still be available. So we don't nuke it entirely; we just make
it seem like qualified import.
- We only shadow *External* names (which come from the main module),
or from earlier GHCi commands. Do not shadow *Internal* names
because in the bracket
[d| class C a where f :: a
f = 4 |]
rnSrcDecls will first call extendGlobalRdrEnvRn with C[f] from the
class decl, and *separately* extend the envt with the value binding.
At that stage, the class op 'f' will have an Internal name.
-}
shadow_name :: GlobalRdrEnv -> Name -> GlobalRdrEnv
shadow_name env name
shadowName :: GlobalRdrEnv -> Name -> GlobalRdrEnv
-- Remove certain old LocalDef GREs that share the same OccName as this new Name.
-- See Note [GlobalRdrEnv shadowing] for details
shadowName env name
= alterOccEnv (fmap alter_fn) env (nameOccName name)
where
alter_fn :: [GlobalRdrElt] -> [GlobalRdrElt]
......@@ -710,23 +728,30 @@ shadow_name env name
shadow_with :: Name -> GlobalRdrElt -> Maybe GlobalRdrElt
shadow_with new_name old_gre@(GRE { gre_name = old_name, gre_prov = LocalDef })
= case (nameModule_maybe old_name, nameModule_maybe new_name) of
(Nothing, _) -> Nothing
(Just old_mod, Just new_mod) | new_mod == old_mod -> Nothing
(Just old_mod, _) -> Just (old_gre { gre_prov = Imported [fake_imp_spec] })
where
fake_imp_spec = ImpSpec id_spec ImpAll -- Urgh!
old_mod_name = moduleName old_mod
id_spec = ImpDeclSpec { is_mod = old_mod_name
, is_as = old_mod_name
, is_qual = True
, is_dloc = nameSrcSpan old_name }
= case nameModule_maybe old_name of
Nothing -> Just old_gre
Just old_mod
| Just new_mod <- nameModule_maybe new_name
, new_mod == old_mod
-> Nothing
| otherwise
-> Just (old_gre { gre_prov = Imported [mk_fake_imp_spec old_name old_mod] })
shadow_with new_name old_gre@(GRE { gre_prov = Imported imp_specs })
| null imp_specs' = Nothing
| otherwise = Just (old_gre { gre_prov = Imported imp_specs' })
where
imp_specs' = mapMaybe (shadow_is new_name) imp_specs
mk_fake_imp_spec old_name old_mod -- Urgh!
= ImpSpec id_spec ImpAll
where
old_mod_name = moduleName old_mod
id_spec = ImpDeclSpec { is_mod = old_mod_name
, is_as = old_mod_name
, is_qual = True
, is_dloc = nameSrcSpan old_name }
shadow_is :: Name -> ImportSpec -> Maybe ImportSpec
shadow_is new_name is@(ImpSpec { is_decl = id_spec })
| Just new_mod <- nameModule_maybe new_name
......@@ -735,41 +760,6 @@ shadow_name env name
| otherwise -- Shadow unqualified only
= Just (is { is_decl = id_spec { is_qual = True } })
{-
Note [Template Haskell binders in the GlobalRdrEnv]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For reasons described in Note [Top-level Names in Template Haskell decl quotes]
in RnNames, a GRE with an Internal gre_name (i.e. one generated by a TH decl
quote) should *shadow* a GRE with an External gre_name. Hence some faffing
around in pickGREs and findLocalDupsRdrEnv
-}
findLocalDupsRdrEnv :: GlobalRdrEnv -> [Name] -> [[GlobalRdrElt]]
-- ^ For each 'OccName', see if there are multiple local definitions
-- for it; return a list of all such
-- and return a list of the duplicate bindings
findLocalDupsRdrEnv rdr_env occs
= go rdr_env [] occs
where
go _ dups [] = dups
go rdr_env dups (name:names)
= case filter (pick name) gres of
[] -> go rdr_env dups names
[_] -> go rdr_env dups names -- The common case
dup_gres -> go rdr_env' (dup_gres : dups) names
where
occ = nameOccName name
gres = lookupOccEnv rdr_env occ `orElse` []
rdr_env' = delFromOccEnv rdr_env occ
-- The delFromOccEnv avoids repeating the same
-- complaint twice, when names itself has a duplicate
-- which is a common case
-- See Note [Template Haskell binders in the GlobalRdrEnv]
pick name (GRE { gre_name = n, gre_prov = LocalDef })
| isInternalName name = isInternalName n
| otherwise = True
pick _ _ = False
{-
************************************************************************
......
......@@ -2,14 +2,14 @@
-----------------------------------------------------------------------------
--
-- GHCi Interactive debugging commands
-- GHCi Interactive debugging commands
--
-- Pepe Iborra (supported by Google SoC) 2006
--
-- ToDo: lots of violation of layering here. This module should
-- decide whether it is above the GHC API (import GHC and nothing
-- else) or below it.
--
--
-----------------------------------------------------------------------------
module Debugger (pprintClosureCommand, showTerm, pprTypeAndContents) where
......@@ -20,6 +20,7 @@ import RtClosureInspect
import GhcMonad
import HscTypes
import Id
import IfaceEnv( newInteractiveBinder )
import Name
import Var hiding ( varName )
import VarSet
......@@ -71,7 +72,7 @@ pprintClosureCommand bindThings force str = do
-- Do the obtainTerm--bindSuspensions-computeSubstitution dance
go :: GhcMonad m => TvSubst -> Id -> m (TvSubst, Term)
go subst id = do
let id' = id `setIdType` substTy subst (idType id)
let id' = id `setIdType` substTy subst (idType id)
term_ <- GHC.obtainTermFromId maxBound force id'
term <- tidyTermTyVars term_
term' <- if bindThings &&
......@@ -112,9 +113,9 @@ bindSuspensions t = do
alreadyUsedNames = map (occNameString . nameOccName . getName) inScope
availNames = map ((prefix++) . show) [(1::Int)..] \\ alreadyUsedNames
availNames_var <- liftIO $ newIORef availNames
(t', stuff) <- liftIO $ foldTerm (nameSuspensionsAndGetInfos availNames_var) t
(t', stuff) <- liftIO $ foldTerm (nameSuspensionsAndGetInfos hsc_env availNames_var) t
let (names, tys, hvals) = unzip3 stuff
let ids = [ mkVanillaGlobal name ty
let ids = [ mkVanillaGlobal name ty
| (name,ty) <- zip names tys]
new_ic = extendInteractiveContextWithIds ictxt ids
liftIO $ extendLinkEnv (zip names hvals)
......@@ -123,27 +124,27 @@ bindSuspensions t = do
where
-- Processing suspensions. Give names and recopilate info
nameSuspensionsAndGetInfos :: IORef [String] ->
TermFold (IO (Term, [(Name,Type,HValue)]))
nameSuspensionsAndGetInfos freeNames = TermFold
nameSuspensionsAndGetInfos :: HscEnv -> IORef [String]
-> TermFold (IO (Term, [(Name,Type,HValue)]))
nameSuspensionsAndGetInfos hsc_env freeNames = TermFold
{
fSuspension = doSuspension freeNames
fSuspension = doSuspension hsc_env freeNames
, fTerm = \ty dc v tt -> do
tt' <- sequence tt
let (terms,names) = unzip tt'
return (Term ty dc v terms, concat names)
, fPrim = \ty n ->return (Prim ty n,[])
, fNewtypeWrap =
\ty dc t -> do
, fNewtypeWrap =
\ty dc t -> do
(term, names) <- t
return (NewtypeWrap ty dc term, names)
, fRefWrap = \ty t -> do
(term, names) <- t
(term, names) <- t
return (RefWrap ty term, names)
}
doSuspension freeNames ct ty hval _name = do
doSuspension hsc_env freeNames ct ty hval _name = do
name <- atomicModifyIORef' freeNames (\x->(tail x, head x))
n <- newGrimName name
n <- newGrimName hsc_env name
return (Suspension ct ty hval (Just n), [(n,ty,hval)])
......@@ -181,7 +182,7 @@ showTerm term = do
`gfinally` do
setSession hsc_env
GHC.setSessionDynFlags dflags
cPprShowable prec NewtypeWrap{ty=new_ty,wrapped_term=t} =
cPprShowable prec NewtypeWrap{ty=new_ty,wrapped_term=t} =
cPprShowable prec t{ty=new_ty}
cPprShowable _ _ = return Nothing
......@@ -192,26 +193,24 @@ showTerm term = do
bindToFreshName hsc_env ty userName = do
name <- newGrimName userName
let id = mkVanillaGlobal name ty
name <- newGrimName hsc_env userName
let id = mkVanillaGlobal name ty
new_ic = extendInteractiveContextWithIds (hsc_IC hsc_env) [id]
return (hsc_env {hsc_IC = new_ic }, name)
-- Create new uniques and give them sequentially numbered names
newGrimName :: MonadIO m => String -> m Name
newGrimName userName = do
us <- liftIO $ mkSplitUniqSupply 'b'
let unique = uniqFromSupply us
occname = mkOccName varName userName
name = mkInternalName unique occname noSrcSpan
return name
newGrimName :: MonadIO m => HscEnv -> String -> m Name
newGrimName hsc_env userName
= liftIO (newInteractiveBinder hsc_env occ noSrcSpan)
where
occ = mkOccName varName userName
pprTypeAndContents :: GhcMonad m => Id -> m SDoc
pprTypeAndContents id = do
dflags <- GHC.getSessionDynFlags
let pcontents = gopt Opt_PrintBindContents dflags
pprdId = (PprTyThing.pprTyThing . AnId) id
if pcontents
if pcontents
then do
let depthBound = 100
-- If the value is an exception, make sure we catch it and
......@@ -225,7 +224,7 @@ pprTypeAndContents id = do
else return pprdId
--------------------------------------------------------------
-- Utils
-- Utils
traceOptIf :: GhcMonad m => DumpFlag -> SDoc -> m ()
traceOptIf flag doc = do
......
......@@ -3,7 +3,8 @@
{-# LANGUAGE CPP, RankNTypes #-}
module IfaceEnv (
newGlobalBinder, newImplicitBinder,
newGlobalBinder, newImplicitBinder, newInteractiveBinder,
externaliseName,
lookupIfaceTop,
lookupOrig, lookupOrigNameCache, extendNameCache,
newIfaceName, newIfaceNames,
......@@ -13,8 +14,9 @@ module IfaceEnv (
ifaceExportNames,
-- Name-cache stuff
allocateGlobalBinder, initNameCache, updNameCache,
getNameCache, mkNameCacheUpdater, NameCacheUpdater(..)
allocateGlobalBinder,
initNameCache, updNameCache,
mkNameCacheUpdater, NameCacheUpdater(..)
) where
#include "HsVersions.h"
......@@ -70,10 +72,18 @@ newGlobalBinder :: Module -> OccName -> SrcSpan -> TcRnIf a b Name
-- moment when we know its Module and SrcLoc in their full glory
newGlobalBinder mod occ loc
= do mod `seq` occ `seq` return () -- See notes with lookupOrig
-- traceIf (text "newGlobalBinder" <+> ppr mod <+> ppr occ <+> ppr loc)
updNameCache $ \name_cache ->
allocateGlobalBinder name_cache mod occ loc
= do { mod `seq` occ `seq` return () -- See notes with lookupOrig
-- ; traceIf (text "newGlobalBinder" <+> ppr mod <+> ppr occ <+> ppr loc)
; updNameCacheTcRn $ \name_cache ->
allocateGlobalBinder name_cache mod occ loc }
newInteractiveBinder :: HscEnv -> OccName -> SrcSpan -> IO Name
-- Works in the IO monad, and gets the Module
-- from the interactive context
newInteractiveBinder hsc_env occ loc
= do { let mod = icInteractiveModule (hsc_IC hsc_env)
; updNameCache hsc_env $ \name_cache ->
allocateGlobalBinder name_cache mod occ loc }
allocateGlobalBinder
:: NameCache
......@@ -150,8 +160,8 @@ lookupOrig mod occ
mod `seq` occ `seq` return ()
-- ; traceIf (text "lookup_orig" <+> ppr mod <+> ppr occ)
; updNameCache $ \name_cache ->
case lookupOrigNameCache (nsNames name_cache) mod occ of {
; updNameCacheTcRn $ \name_cache ->
case lookupOrigNameCache (nsNames name_cache) mod occ of {
Just name -> (name_cache, name);
Nothing ->
case takeUniqFromSupply (nsUniqs name_cache) of {
......@@ -162,6 +172,19 @@ lookupOrig mod occ
in (name_cache{ nsUniqs = us, nsNames = new_cache }, name)
}}}
externaliseName :: Module -> Name -> TcRnIf m n Name
-- Take an Internal Name and make it an External one,
-- with the same unique
externaliseName mod name
= do { let occ = nameOccName name
loc = nameSrcSpan name
uniq = nameUnique name
; occ `seq` return () -- c.f. seq in newGlobalBinder
; updNameCacheTcRn $ \ ns ->
let name' = mkExternalName uniq mod occ loc
ns' = ns { nsNames = extendNameCache (nsNames ns) mod occ name' }
in (ns', name') }
{-
************************************************************************
* *
......@@ -214,26 +237,23 @@ extendNameCache nc mod occ name
where
combine _ occ_env = extendOccEnv occ_env occ name
getNameCache :: TcRnIf a b NameCache
getNameCache = do { HscEnv { hsc_NC = nc_var } <- getTopEnv;
readMutVar nc_var }
updNameCacheTcRn :: (NameCache -> (NameCache, c)) -> TcRnIf a b c
updNameCacheTcRn upd_fn = do { hsc_env <- getTopEnv
; liftIO (updNameCache hsc_env upd_fn) }
updNameCache :: (NameCache -> (NameCache, c)) -> TcRnIf a b c
updNameCache upd_fn = do
HscEnv { hsc_NC = nc_var } <- getTopEnv
atomicUpdMutVar' nc_var upd_fn
updNameCache :: HscEnv -> (NameCache -> (NameCache, c)) -> IO c
updNameCache hsc_env upd_fn = atomicModifyIORef' (hsc_NC hsc_env) upd_fn
-- | A function that atomically updates the name cache given a modifier
-- function. The second result of the modifier function will be the result
-- of the IO action.
newtype NameCacheUpdater = NCU { updateNameCache :: forall c. (NameCache -> (NameCache, c)) -> IO c }
newtype NameCacheUpdater
= NCU { updateNameCache :: forall c. (NameCache -> (NameCache, c)) -> IO c }
-- | Return a function to atomically update the name cache.
mkNameCacheUpdater :: TcRnIf a b NameCacheUpdater
mkNameCacheUpdater = do
nc_var <- hsc_NC `fmap` getTopEnv
let update_nc f = atomicModifyIORef' nc_var f
return (NCU update_nc)
mkNameCacheUpdater = do { hsc_env <- getTopEnv
; return (NCU (updNameCache hsc_env)) }
initNameCache :: UniqSupply -> [Name] -> NameCache
initNameCache us names
......
......@@ -1159,7 +1159,7 @@ appendStubC (ForeignStubs h c) c_code = ForeignStubs h (c $$ c_code)
{-
************************************************************************
* *
\subsection{The interactive context}
The interactive context
* *
************************************************************************
......@@ -1235,28 +1235,40 @@ The details are a bit tricky though:
Note [Interactively-bound Ids in GHCi]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Ids bound by previous Stmts in GHCi are currently
a) GlobalIds
b) with an Internal Name (not External)
c) and a tidied type
a) GlobalIds, with
b) An External Name, like Ghci4.foo
See Note [The interactive package] above
c) A tidied type
(a) They must be GlobalIds (not LocalIds) otherwise when we come to
compile an expression using these ids later, the byte code
generator will consider the occurrences to be free rather than
global.
(b) They start with an Internal Name because a Stmt is a local
construct, so the renamer naturally builds an Internal name for
each of its binders. It would be possible subsequently to give
them an External Name (in a GhciN module) but then we'd have
to substitute it out. So for now they stay Internal.
(b) Having an External Name is important because of Note
[GlobalRdrEnv shadowing] in RdrName
(c) Their types are tidied. This is important, because :info may ask
to look at them, and :info expects the things it looks up to have
tidy types
However note that TyCons, Classes, and even Ids bound by other top-level
declarations in GHCi (eg foreign import, record selectors) currently get
External Names, with Ghci9 (or 8, or 7, etc) as the module name.
Where do interactively-bound Ids come from?
- GHCi REPL Stmts e.g.
ghci> let foo x = x+1
These start with an Internal Name because a Stmt is a local
construct, so the renamer naturally builds an Internal name for
each of its binders. Then in tcRnStmt they are externalised via
TcRnDriver.externaliseAndTidyId, so they get Names like Ghic4.foo.
- Ids bound by the debugger etc have Names constructed by
IfaceEnv.newInteractiveBinder; at the call sites it is followed by
mkVanillaGlobal or mkVanillaGlobalWithInfo. So again, they are
all Global, External.
- TyCons, Classes, and Ids bound by other top-level declarations in
GHCi (eg foreign import, record selectors) also get External
Names, with Ghci9 (or 8, or 7, etc) as the module name.
Note [ic_tythings]
......@@ -1462,9 +1474,11 @@ icExtendGblRdrEnv env tythings
= foldr add env tythings -- Foldr makes things in the front of
-- the list shadow things at the back
where
add thing env = extendGlobalRdrEnv True {- Shadowing please -} env
[tyThingAvailInfo thing]
-- One at a time, to ensure each shadows the previous ones
-- One at a time, to ensure each shadows the previous ones
add thing env = foldl extendGlobalRdrEnv env1 (localGREsFromAvail avail)
where
env1 = shadowNames env (availNames avail)
avail = tyThingAvailInfo thing
substInteractiveContext :: InteractiveContext -> TvSubst -> InteractiveContext
substInteractiveContext ictxt@InteractiveContext{ ic_tythings = tts } subst
......
......@@ -52,6 +52,7 @@ import HsSyn
import HscTypes
import BasicTypes ( HValue )
import InstEnv
import IfaceEnv ( newInteractiveBinder )
import FamInstEnv ( FamInst, orphNamesOfFamInst )
import TyCon
import Type hiding( typeKind )
......@@ -69,6 +70,7 @@ import Linker
import DynFlags
import Unique
import UniqSupply
import MonadUtils
import Module
import Panic
import UniqFM
......@@ -187,7 +189,7 @@ execStmt stmt ExecOptions{..} = do
-- empty statement / comment
Nothing -> return (ExecComplete (Right []) 0)
Just (tyThings, hval, fix_env) -> do
Just (ids, hval, fix_env) -> do
updateFixityEnv fix_env
status <-
......@@ -201,7 +203,7 @@ execStmt stmt ExecOptions{..} = do
size = ghciHistSize idflags'
handleRunStatus execSingleStep stmt bindings tyThings
handleRunStatus execSingleStep stmt bindings ids
breakMVar statusMVar status (emptyHistory size)
-- | The type returned by the deprecated 'runStmt' and
......@@ -626,17 +628,18 @@ bindLocalsAtBreakpoint
-- bind, all we can do is bind a local variable to the exception
<