diff options
| -rw-r--r-- | compiler/rename/RnUnbound.hs | 53 | ||||
| -rw-r--r-- | compiler/typecheck/TcErrors.hs | 4 | ||||
| -rw-r--r-- | testsuite/tests/module/mod62.stderr | 1 | ||||
| -rw-r--r-- | testsuite/tests/rename/should_fail/T15611a.hs | 2 | ||||
| -rw-r--r-- | testsuite/tests/rename/should_fail/T15611a.stderr | 1 | ||||
| -rw-r--r-- | testsuite/tests/rename/should_fail/T15611b.hs | 1 | ||||
| -rw-r--r-- | testsuite/tests/rename/should_fail/T15611b.script | 2 | ||||
| -rw-r--r-- | testsuite/tests/rename/should_fail/T15611b.stderr | 1 | ||||
| -rw-r--r-- | testsuite/tests/rename/should_fail/T5892b.stderr | 4 | ||||
| -rw-r--r-- | testsuite/tests/rename/should_fail/all.T | 2 | ||||
| -rw-r--r-- | testsuite/tests/rename/should_fail/rnfail034.stderr | 1 |
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. |
