summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/rename/RnUnbound.hs53
-rw-r--r--compiler/typecheck/TcErrors.hs4
-rw-r--r--testsuite/tests/module/mod62.stderr1
-rw-r--r--testsuite/tests/rename/should_fail/T15611a.hs2
-rw-r--r--testsuite/tests/rename/should_fail/T15611a.stderr1
-rw-r--r--testsuite/tests/rename/should_fail/T15611b.hs1
-rw-r--r--testsuite/tests/rename/should_fail/T15611b.script2
-rw-r--r--testsuite/tests/rename/should_fail/T15611b.stderr1
-rw-r--r--testsuite/tests/rename/should_fail/T5892b.stderr4
-rw-r--r--testsuite/tests/rename/should_fail/all.T2
-rw-r--r--testsuite/tests/rename/should_fail/rnfail034.stderr1
11 files changed, 60 insertions, 12 deletions
diff --git a/compiler/rename/RnUnbound.hs b/compiler/rename/RnUnbound.hs
index ce5d0dc315..97d3fd7279 100644
--- a/compiler/rename/RnUnbound.hs
+++ b/compiler/rename/RnUnbound.hs
@@ -24,13 +24,14 @@ import Name
import Module
import SrcLoc
import Outputable
-import PrelNames ( mkUnboundName, forall_tv_RDR, isUnboundName )
+import PrelNames ( mkUnboundName, forall_tv_RDR, isUnboundName, getUnique)
import Util
import Maybes
import DynFlags
import FastString
import Data.List
import Data.Function ( on )
+import UniqDFM (udfmToList)
{-
************************************************************************
@@ -67,8 +68,11 @@ unboundNameX where_look rdr_name extra
else do { local_env <- getLocalRdrEnv
; global_env <- getGlobalRdrEnv
; impInfo <- getImports
+ ; currmod <- getModule
+ ; hpt <- getHpt
; let suggestions = unknownNameSuggestions_ where_look
- dflags global_env local_env impInfo rdr_name
+ dflags hpt currmod global_env local_env impInfo
+ rdr_name
; addErr (err $$ suggestions) }
; return (mkUnboundNameRdr rdr_name) }
@@ -89,16 +93,19 @@ type HowInScope = Either SrcSpan ImpDeclSpec
-- | Called from the typechecker (TcErrors) when we find an unbound variable
unknownNameSuggestions :: DynFlags
+ -> HomePackageTable -> Module
-> GlobalRdrEnv -> LocalRdrEnv -> ImportAvails
-> RdrName -> SDoc
unknownNameSuggestions = unknownNameSuggestions_ WL_Any
unknownNameSuggestions_ :: WhereLooking -> DynFlags
+ -> HomePackageTable -> Module
-> GlobalRdrEnv -> LocalRdrEnv -> ImportAvails
-> RdrName -> SDoc
-unknownNameSuggestions_ where_look dflags global_env local_env imports tried_rdr_name =
+unknownNameSuggestions_ where_look dflags hpt curr_mod global_env local_env
+ imports tried_rdr_name =
similarNameSuggestions where_look dflags global_env local_env tried_rdr_name $$
- importSuggestions where_look imports tried_rdr_name $$
+ importSuggestions where_look hpt curr_mod imports tried_rdr_name $$
extensionSuggestions tried_rdr_name
@@ -223,12 +230,15 @@ similarNameSuggestions where_look dflags global_env
| i <- is, let ispec = is_decl i, is_qual ispec ]
-- | Generate helpful suggestions if a qualified name Mod.foo is not in scope.
-importSuggestions :: WhereLooking -> ImportAvails -> RdrName -> SDoc
-importSuggestions where_look imports rdr_name
+importSuggestions :: WhereLooking
+ -> HomePackageTable -> Module
+ -> ImportAvails -> RdrName -> SDoc
+importSuggestions where_look hpt currMod imports rdr_name
| WL_LocalOnly <- where_look = Outputable.empty
| not (isQual rdr_name || isUnqual rdr_name) = Outputable.empty
| null interesting_imports
, Just name <- mod_name
+ , showNotImportedLine (fromJust mod_name)
= hsep
[ text "No module named"
, quotes (ppr name)
@@ -245,6 +255,7 @@ importSuggestions where_look imports rdr_name
]
| is_qualified
, null helpful_imports
+ , not (null interesting_imports)
, mods <- map fst interesting_imports
= hsep
[ text "Neither"
@@ -330,6 +341,19 @@ importSuggestions where_look imports rdr_name
(helpful_imports_hiding, helpful_imports_non_hiding)
= partition (imv_is_hiding . snd) helpful_imports
+ -- See note [showNotImportedLine]
+ showNotImportedLine :: ModuleName -> Bool -- #15611
+ showNotImportedLine modnam
+ | modnam `elem`
+ fmap moduleName (moduleEnvKeys (imp_mods imports)) = False -- 1
+ | moduleName currMod == modnam = False -- 2.1
+ | isLastLoadedMod modnam hptUniques = False -- 2.2
+ | otherwise = True
+ where
+ hptUniques = map fst (udfmToList hpt)
+ isLastLoadedMod _ [] = False
+ isLastLoadedMod modnam uniqs = last uniqs == getUnique modnam
+
extensionSuggestions :: RdrName -> SDoc
extensionSuggestions rdrName
| rdrName == mkUnqual varName (fsLit "mdo") ||
@@ -341,3 +365,20 @@ perhapsForallMsg :: SDoc
perhapsForallMsg
= vcat [ text "Perhaps you intended to use ExplicitForAll or similar flag"
, text "to enable explicit-forall syntax: forall <tvs>. <type>"]
+
+{- Note [showNotImportedLine] -- #15611
+For the error message:
+ Not in scope X.Y
+ Module X does not export Y
+ No module named ‘X’ is imported:
+there are 2 cases, where we hide the last "no module is imported" line:
+1. If the module X has been imported.
+2. If the module X is the current module. There are 2 subcases:
+ 2.1 If the unknown module name is in a input source file,
+ then we can use the getModule function to get the current module name.
+ (See test T15611a)
+ 2.2 If the unknown module name has been entered by the user in GHCi,
+ then the getModule function returns something like "interactive:Ghci1",
+ and we have to check the current module in the last added entry of
+ the HomePackageTable. (See test T15611b)
+-}
diff --git a/compiler/typecheck/TcErrors.hs b/compiler/typecheck/TcErrors.hs
index 1fd98f1aa5..c692b7b905 100644
--- a/compiler/typecheck/TcErrors.hs
+++ b/compiler/typecheck/TcErrors.hs
@@ -1091,7 +1091,9 @@ mkHoleError _ _ ct@(CHoleCan { cc_hole = ExprHole (OutOfScope occ rdr_env0) })
-- in-scope variables in the message, and note inaccessible exact matches
= do { dflags <- getDynFlags
; imp_info <- getImports
- ; let suggs_msg = unknownNameSuggestions dflags rdr_env0
+ ; curr_mod <- getModule
+ ; hpt <- getHpt
+ ; let suggs_msg = unknownNameSuggestions dflags hpt curr_mod rdr_env0
(tcl_rdr lcl_env) imp_info rdr
; rdr_env <- getGlobalRdrEnv
; splice_locs <- getTopLevelSpliceLocs
diff --git a/testsuite/tests/module/mod62.stderr b/testsuite/tests/module/mod62.stderr
index 3a6f415946..0a2ceff6d9 100644
--- a/testsuite/tests/module/mod62.stderr
+++ b/testsuite/tests/module/mod62.stderr
@@ -4,4 +4,3 @@ mod62.hs:3:9: error: Qualified name in binding position: M.y
mod62.hs:3:22: error:
Not in scope: ‘M.y’
Perhaps you meant ‘M.x’ (line 3)
- No module named ‘M’ is imported.
diff --git a/testsuite/tests/rename/should_fail/T15611a.hs b/testsuite/tests/rename/should_fail/T15611a.hs
new file mode 100644
index 0000000000..df1bb2f08c
--- /dev/null
+++ b/testsuite/tests/rename/should_fail/T15611a.hs
@@ -0,0 +1,2 @@
+main :: IO ()
+main = Main.foo
diff --git a/testsuite/tests/rename/should_fail/T15611a.stderr b/testsuite/tests/rename/should_fail/T15611a.stderr
new file mode 100644
index 0000000000..ebeb83b5f2
--- /dev/null
+++ b/testsuite/tests/rename/should_fail/T15611a.stderr
@@ -0,0 +1 @@
+T15611a.hs:2:8: Not in scope: ‘Main.foo’
diff --git a/testsuite/tests/rename/should_fail/T15611b.hs b/testsuite/tests/rename/should_fail/T15611b.hs
new file mode 100644
index 0000000000..0ab721d1d1
--- /dev/null
+++ b/testsuite/tests/rename/should_fail/T15611b.hs
@@ -0,0 +1 @@
+module T15611b where
diff --git a/testsuite/tests/rename/should_fail/T15611b.script b/testsuite/tests/rename/should_fail/T15611b.script
new file mode 100644
index 0000000000..d2b1fb1458
--- /dev/null
+++ b/testsuite/tests/rename/should_fail/T15611b.script
@@ -0,0 +1,2 @@
+:l T15611b
+T15611b.foo
diff --git a/testsuite/tests/rename/should_fail/T15611b.stderr b/testsuite/tests/rename/should_fail/T15611b.stderr
new file mode 100644
index 0000000000..609ab4c041
--- /dev/null
+++ b/testsuite/tests/rename/should_fail/T15611b.stderr
@@ -0,0 +1 @@
+<interactive>:2:1: Not in scope: ‘T15611b.foo’
diff --git a/testsuite/tests/rename/should_fail/T5892b.stderr b/testsuite/tests/rename/should_fail/T5892b.stderr
index 0f93c21f68..d55d0cb8e1 100644
--- a/testsuite/tests/rename/should_fail/T5892b.stderr
+++ b/testsuite/tests/rename/should_fail/T5892b.stderr
@@ -1,4 +1,2 @@
-T5892b.hs:11:7: error:
- Not in scope: ‘T5892b.subForest’
- No module named ‘T5892b’ is imported.
+T5892b.hs:11:7: error: Not in scope: ‘T5892b.subForest’
diff --git a/testsuite/tests/rename/should_fail/all.T b/testsuite/tests/rename/should_fail/all.T
index 6debe7b917..9ca330f873 100644
--- a/testsuite/tests/rename/should_fail/all.T
+++ b/testsuite/tests/rename/should_fail/all.T
@@ -138,5 +138,7 @@ test('T15539', normal, compile_fail, [''])
test('T15487', normal, multimod_compile_fail, ['T15487','-v0'])
test('T15659', normal, compile_fail, [''])
test('T15607', normal, compile_fail, [''])
+test('T15611a', normal, compile_fail, [''])
+test('T15611b', normal, ghci_script, ['T15611b.script'])
test('ExplicitForAllRules2', normal, compile_fail, [''])
diff --git a/testsuite/tests/rename/should_fail/rnfail034.stderr b/testsuite/tests/rename/should_fail/rnfail034.stderr
index 63e6eb5037..a5219c138b 100644
--- a/testsuite/tests/rename/should_fail/rnfail034.stderr
+++ b/testsuite/tests/rename/should_fail/rnfail034.stderr
@@ -4,4 +4,3 @@ rnfail034.hs:4:11: error: Qualified name in binding position: M.y
rnfail034.hs:4:26: error:
Not in scope: ‘M.y’
Perhaps you meant ‘M.g’ (line 4)
- No module named ‘M’ is imported.