summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoachim Breitner <mail@joachim-breitner.de>2021-10-10 11:13:49 +0200
committerJoachim Breitner <mail@joachim-breitner.de>2021-10-16 09:05:57 +0200
commit8cbd3d3feefad52ea5c54055212ff9b14866dfef (patch)
tree3cfe257d1c6b6544488fe4fa7f40972778712c53
parent2a8d951f965a8369f1a9d487e45110c4a5604918 (diff)
downloadhaskell-8cbd3d3feefad52ea5c54055212ff9b14866dfef.tar.gz
Ghci environment: Do not remove shadowed ids
previously defined names need to be kept around, e.g. for type signatures: ``` ghci> data T = T ghci> let t = T ghci> data T = T ghci> :t t t :: Ghci1.T ``` and indeed they can be used: ``` ghci> let t2 = Ghci1.T :: Ghci1.T ghci> :t t2 t2 :: Ghci1.T ``` However, previously this did not work for ids (non-types), although they are still around under the qualified name internally: ``` ghci> let t = "other t" ghci> t' <interactive>:8:1: error: • Variable not in scope: t' • Perhaps you meant one of these: ‘Ghci2.t’ (imported from Ghci2), ‘t’ (line 7), ‘t2’ (line 5) ghci> Ghci2.t <interactive>:9:1: error: • GHC internal error: ‘Ghci2.t’ is not in scope during type checking, but it passed the renamer tcl_env of environment: [] • In the expression: Ghci2.t In an equation for ‘it’: it = Ghci2.t ``` This fixes the problem by simply removing the code that tries to remove shadowed ids from the environment. Now you can refer to shadowed ids using `Ghci2.t`, just like you can do for data and type constructors. This simplifies the code, makes terms and types more similar, and also fixes #20455.
-rw-r--r--compiler/GHC/Runtime/Context.hs25
-rw-r--r--testsuite/tests/ghci/scripts/T20455.script17
-rw-r--r--testsuite/tests/ghci/scripts/T20455.stderr10
-rw-r--r--testsuite/tests/ghci/scripts/T20455.stdout5
-rwxr-xr-xtestsuite/tests/ghci/scripts/all.T1
5 files changed, 38 insertions, 20 deletions
diff --git a/compiler/GHC/Runtime/Context.hs b/compiler/GHC/Runtime/Context.hs
index 6fa5ed8130..c9f30978c0 100644
--- a/compiler/GHC/Runtime/Context.hs
+++ b/compiler/GHC/Runtime/Context.hs
@@ -32,7 +32,6 @@ import GHC.Core.Type
import GHC.Types.Avail
import GHC.Types.Fixity.Env
-import GHC.Types.Id ( isRecordSelector )
import GHC.Types.Id.Info ( IdDetails(..) )
import GHC.Types.Name
import GHC.Types.Name.Env
@@ -332,11 +331,9 @@ icPrintUnqual :: UnitEnv -> InteractiveContext -> PrintUnqualified
icPrintUnqual unit_env ictxt = mkPrintUnqualified unit_env (icReaderEnv ictxt)
-- | extendInteractiveContext is called with new TyThings recently defined to update the
--- InteractiveContext to include them. Ids are easily removed when shadowed,
--- but Classes and TyCons are not. Some work could be done to determine
--- whether they are entirely shadowed, but as you could still have references
--- to them (e.g. instances for classes or values of the type for TyCons), it's
--- not clear whether removing them is even the appropriate behavior.
+-- InteractiveContext to include them. By putting new things first, unqualified
+-- use will pick the most recently defined thing with a given name, while
+-- still keeping the old names in scope in their qualified form (Ghci1.foo).
extendInteractiveContext :: InteractiveContext
-> [TyThing]
-> [ClsInst] -> [FamInst]
@@ -347,7 +344,7 @@ extendInteractiveContext ictxt new_tythings new_cls_insts new_fam_insts defaults
= ictxt { ic_mod_index = ic_mod_index ictxt + 1
-- Always bump this; even instances should create
-- a new mod_index (#9426)
- , ic_tythings = new_tythings ++ old_tythings
+ , ic_tythings = new_tythings ++ ic_tythings ictxt
, ic_gre_cache = ic_gre_cache ictxt `icExtendIcGblRdrEnv` new_tythings
, ic_instances = ( new_cls_insts ++ old_cls_insts
, new_fam_insts ++ fam_insts )
@@ -357,9 +354,6 @@ extendInteractiveContext ictxt new_tythings new_cls_insts new_fam_insts defaults
, ic_fix_env = fix_env -- See Note [Fixity declarations in GHCi]
}
where
- new_ids = [id | AnId id <- new_tythings]
- old_tythings = filterOut (shadowed_by new_ids) (ic_tythings ictxt)
-
-- Discard old instances that have been fully overridden
-- See Note [Override identical instances in GHCi]
(cls_insts, fam_insts) = ic_instances ictxt
@@ -371,20 +365,11 @@ extendInteractiveContextWithIds ictxt new_ids
| null new_ids = ictxt
| otherwise
= ictxt { ic_mod_index = ic_mod_index ictxt + 1
- , ic_tythings = new_tythings ++ old_tythings
+ , ic_tythings = new_tythings ++ ic_tythings ictxt
, ic_gre_cache = ic_gre_cache ictxt `icExtendIcGblRdrEnv` new_tythings
}
where
new_tythings = map AnId new_ids
- old_tythings = filterOut (shadowed_by new_ids) (ic_tythings ictxt)
-
-shadowed_by :: [Id] -> TyThing -> Bool
-shadowed_by ids = shadowed
- where
- -- Keep record selectors because they might be needed by HasField (#19322)
- shadowed (AnId id) | isRecordSelector id = False
- shadowed tything = getOccName tything `elemOccSet` new_occs
- new_occs = mkOccSet (map getOccName ids)
setInteractivePrintName :: InteractiveContext -> Name -> InteractiveContext
setInteractivePrintName ic n = ic{ic_int_print = n}
diff --git a/testsuite/tests/ghci/scripts/T20455.script b/testsuite/tests/ghci/scripts/T20455.script
new file mode 100644
index 0000000000..a3261fe91c
--- /dev/null
+++ b/testsuite/tests/ghci/scripts/T20455.script
@@ -0,0 +1,17 @@
+let l = "first l"
+let l = "second l"
+ll -- should not recommend Ghci.l
+Ghci1.l
+l
+:info Ghci1.l
+:browse Ghci1
+
+-- Now the same for types
+data T = T
+t = T :: T
+data T = T
+:info t
+:type t
+t2 = Ghci5.T :: Ghci5.T
+
+
diff --git a/testsuite/tests/ghci/scripts/T20455.stderr b/testsuite/tests/ghci/scripts/T20455.stderr
new file mode 100644
index 0000000000..cb94e6ee3d
--- /dev/null
+++ b/testsuite/tests/ghci/scripts/T20455.stderr
@@ -0,0 +1,10 @@
+
+<interactive>:3:1: error:
+ • Variable not in scope: ll
+ • Perhaps you meant one of these:
+ ‘Ghci1.l’ (imported from Ghci1), ‘l’ (line 2),
+ ‘all’ (imported from Prelude)
+
+<no location info>: error:
+ Could not find module ‘Ghci1’
+ It is not a module in the current program, or in any known package.
diff --git a/testsuite/tests/ghci/scripts/T20455.stdout b/testsuite/tests/ghci/scripts/T20455.stdout
new file mode 100644
index 0000000000..8687a8e0b5
--- /dev/null
+++ b/testsuite/tests/ghci/scripts/T20455.stdout
@@ -0,0 +1,5 @@
+"first l"
+"second l"
+Ghci1.l :: String -- Defined at <interactive>:1:5
+t :: Ghci5.T -- Defined at <interactive>:11:1
+t :: Ghci5.T
diff --git a/testsuite/tests/ghci/scripts/all.T b/testsuite/tests/ghci/scripts/all.T
index d8c80e9543..cf6633ceee 100755
--- a/testsuite/tests/ghci/scripts/all.T
+++ b/testsuite/tests/ghci/scripts/all.T
@@ -346,3 +346,4 @@ test('T19650',
test('T20019', normal, ghci_script, ['T20019.script'])
test('T20101', normal, ghci_script, ['T20101.script'])
test('T20206', normal, ghci_script, ['T20206.script'])
+test('T20455', normal, ghci_script, ['T20455.script'])