diff options
author | Joachim Breitner <mail@joachim-breitner.de> | 2021-12-12 15:47:29 +0100 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2021-12-14 20:52:00 -0500 |
commit | a5d8d47f2a95de4b66c7299c25c301b89e6252f6 (patch) | |
tree | c218f03c01469ceb38978b2609f2217036d4432c /testsuite | |
parent | 1c8d609a0509d99722ccc0056dbf3336904bf102 (diff) | |
download | haskell-a5d8d47f2a95de4b66c7299c25c301b89e6252f6.tar.gz |
Ghci environment: Do not remove shadowed ids
Names defined earier but shadowed 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 happen 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.
Now all names ever defined in GHCi are in `ic_tythings`, which is printed by
`:show bindings`. But for that commands, it seems to be more ergonomic
to only list those bindings that are not shadowed. Or, even if it is not
more ergonomic, it’s the current behavour. So let's restore that by filtering
in `icInScopeTTs`.
Of course a single `TyThing` can be associated with many names. We keep
it it in the bindings if _any_ of its names are still visible
unqualifiedly. It's a judgement call.
This commit also turns a rather old comment into a test files.
The comment is is rather stale and things are better explained
elsewhere. Fixes #925.
Two test cases are regressing:
T14052(ghci) ghc/alloc 2749444288.0 12192109912.0 +343.4% BAD
T14052Type(ghci) ghc/alloc 7365784616.0 10767078344.0 +46.2% BAD
This is not unexpected; the `ic_tythings list grows` a lot more if we
don’t remove shadowed Ids. I tried to alleviate it a bit with earlier
MRs, but couldn’t make up for it completely.
Metric Increase:
T14052
T14052Type
Diffstat (limited to 'testsuite')
-rw-r--r-- | testsuite/tests/ghci/scripts/T11547.stderr | 5 | ||||
-rw-r--r-- | testsuite/tests/ghci/scripts/T11547.stdout | 1 | ||||
-rw-r--r-- | testsuite/tests/ghci/scripts/T20455.script | 17 | ||||
-rw-r--r-- | testsuite/tests/ghci/scripts/T20455.stderr | 10 | ||||
-rw-r--r-- | testsuite/tests/ghci/scripts/T20455.stdout | 5 | ||||
-rw-r--r-- | testsuite/tests/ghci/scripts/T925.script | 7 | ||||
-rw-r--r-- | testsuite/tests/ghci/scripts/T925.stdout | 2 | ||||
-rwxr-xr-x | testsuite/tests/ghci/scripts/all.T | 3 | ||||
-rw-r--r-- | testsuite/tests/ghci/scripts/shadow-bindings.script | 48 | ||||
-rw-r--r-- | testsuite/tests/ghci/scripts/shadow-bindings.stdout | 41 |
10 files changed, 134 insertions, 5 deletions
diff --git a/testsuite/tests/ghci/scripts/T11547.stderr b/testsuite/tests/ghci/scripts/T11547.stderr deleted file mode 100644 index 2623e4659f..0000000000 --- a/testsuite/tests/ghci/scripts/T11547.stderr +++ /dev/null @@ -1,5 +0,0 @@ - -<interactive>:1:1: error: - • GHC internal error: ‘Ghci1.foo’ is not in scope during type checking, but it passed the renamer - tcl_env of environment: [] - • In the expression: Ghci1.foo diff --git a/testsuite/tests/ghci/scripts/T11547.stdout b/testsuite/tests/ghci/scripts/T11547.stdout index f808e0c90e..6f2a8333c3 100644 --- a/testsuite/tests/ghci/scripts/T11547.stdout +++ b/testsuite/tests/ghci/scripts/T11547.stdout @@ -1,4 +1,5 @@ Ghci1.foo :: t Ghci2.foo :: t +Ghci1.foo :: t Foo :: Ghci3.Foo Ghci3.Bar :: Ghci3.Foo 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/T925.script b/testsuite/tests/ghci/scripts/T925.script new file mode 100644 index 0000000000..ce003174f7 --- /dev/null +++ b/testsuite/tests/ghci/scripts/T925.script @@ -0,0 +1,7 @@ +:set -XTemplateHaskell +let f n = n * 2::Int +import Language.Haskell.TH +fName <- runQ [| f |] +$(return $ AppE fName (LitE (IntegerL 7))) +let f n = n * 3::Int +$(return $ AppE fName (LitE (IntegerL 7))) diff --git a/testsuite/tests/ghci/scripts/T925.stdout b/testsuite/tests/ghci/scripts/T925.stdout new file mode 100644 index 0000000000..e7376ef157 --- /dev/null +++ b/testsuite/tests/ghci/scripts/T925.stdout @@ -0,0 +1,2 @@ +14 +14 diff --git a/testsuite/tests/ghci/scripts/all.T b/testsuite/tests/ghci/scripts/all.T index 884df5a811..abecdcd76e 100755 --- a/testsuite/tests/ghci/scripts/all.T +++ b/testsuite/tests/ghci/scripts/all.T @@ -346,6 +346,9 @@ test('T20019', normal, ghci_script, ['T20019.script']) test('T20101', normal, ghci_script, ['T20101.script']) test('T20206', normal, ghci_script, ['T20206.script']) test('T20217', normal, ghci_script, ['T20217.script']) +test('T20455', normal, ghci_script, ['T20455.script']) +test('shadow-bindings', normal, ghci_script, ['shadow-bindings.script']) +test('T925', normal, ghci_script, ['T925.script']) test('T7388', normal, ghci_script, ['T7388.script']) test('T20627', normal, ghci_script, ['T20627.script']) test('T20473a', normal, ghci_script, ['T20473a.script']) diff --git a/testsuite/tests/ghci/scripts/shadow-bindings.script b/testsuite/tests/ghci/scripts/shadow-bindings.script new file mode 100644 index 0000000000..6918ad9298 --- /dev/null +++ b/testsuite/tests/ghci/scripts/shadow-bindings.script @@ -0,0 +1,48 @@ +-- Exercising the behaviour of :show bindings and shadowing +let foo = True +foo && True +putStrLn "Expecting foo = True" +:show bindings + +let foo = False +foo && True +putStrLn "Expecting foo = False" +:show bindings +:reload + +data T = A | B +:show bindings +-- shadow T +data T = C +putStrLn "Expecting T and Ghci1.T" +:show bindings +:reload + +data T = A | B +-- shadow just A and B +data T' = A | B' +putStrLn "Expecting T and T'" +:show bindings +:reload + + +data T = A | B +-- shadow all +data T = A | B | C +putStrLn "Expecting only T, no Ghci1.T" +:show bindings +:reload + + +-- Now with record selectors +data T = A {foo :: Bool} +putStrLn "Expecting T and foo with function type" +:show bindings +let foo = True +putStrLn "Expecting T and foo :: Bool" +:show bindings +data T = A +putStrLn "Expecting foo, T" +:show bindings + + diff --git a/testsuite/tests/ghci/scripts/shadow-bindings.stdout b/testsuite/tests/ghci/scripts/shadow-bindings.stdout new file mode 100644 index 0000000000..ef7d5bc9c6 --- /dev/null +++ b/testsuite/tests/ghci/scripts/shadow-bindings.stdout @@ -0,0 +1,41 @@ +True +Expecting foo = True +foo :: Bool = True +it :: () = () +False +Expecting foo = False +foo :: Bool = False +it :: () = () +type T :: * +data T = ... +Expecting T and Ghci1.T +type Ghci1.T :: * +data Ghci1.T = ... +type T :: * +data T = ... +it :: () = () +Expecting T and T' +type T :: * +data T = ... +type T' :: * +data T' = ... +it :: () = () +Expecting only T, no Ghci1.T +type T :: * +data T = ... +it :: () = () +Expecting T and foo with function type +type T :: * +data T = ... +foo :: T -> Bool = _ +it :: () = () +Expecting T and foo :: Bool +type T :: * +data T = ... +foo :: Bool = True +it :: () = () +Expecting foo, T +foo :: Bool = True +type T :: * +data T = ... +it :: () = () |