Give helpful advice when a fully qualified name is not in scope
authorJoachim Breitner <mail@joachim-breitner.de>
Tue, 10 Nov 2015 16:07:10 +0000 (17:07 +0100)
committerJoachim Breitner <mail@joachim-breitner.de>
Fri, 13 Nov 2015 09:13:20 +0000 (10:13 +0100)
This implements #11071. It needs to thread through a GlobalRdrEnv
corresponding to the export list of the module if its exports were not
restricted.

A refactoring of ImportedModsVal into a proper data type follows.

Differential Revision: https://phabricator.haskell.org/D1462

31 files changed:
compiler/iface/MkIface.hs
compiler/main/HscMain.hs
compiler/main/HscTypes.hs
compiler/rename/RnEnv.hs
compiler/rename/RnNames.hs
compiler/typecheck/TcRnTypes.hs
compiler/utils/Outputable.hs
testsuite/tests/ghc-api/annotations/T10313.stderr
testsuite/tests/ghc-api/annotations/T10399.stderr
testsuite/tests/ghci/scripts/T2452.stderr
testsuite/tests/ghci/scripts/T8639.stderr
testsuite/tests/ghci/scripts/ghci036.stderr
testsuite/tests/module/mod134.stderr
testsuite/tests/module/mod62.stderr
testsuite/tests/module/mod73.stderr
testsuite/tests/module/mod74.stderr
testsuite/tests/module/mod88.stderr
testsuite/tests/rename/prog002/rename.prog002.stderr
testsuite/tests/rename/should_fail/T10781.stderr
testsuite/tests/rename/should_fail/T11071.hs [new file with mode: 0644]
testsuite/tests/rename/should_fail/T11071.stderr [new file with mode: 0644]
testsuite/tests/rename/should_fail/T2901.stderr
testsuite/tests/rename/should_fail/T5657.stderr
testsuite/tests/rename/should_fail/T5892b.stderr
testsuite/tests/rename/should_fail/all.T
testsuite/tests/rename/should_fail/rnfail030.stderr
testsuite/tests/rename/should_fail/rnfail031.stderr
testsuite/tests/rename/should_fail/rnfail032.stderr
testsuite/tests/rename/should_fail/rnfail033.stderr
testsuite/tests/rename/should_fail/rnfail034.stderr
testsuite/tests/safeHaskell/ghci/p4.stderr

index d48d6e7..c8830b6 100644 (file)
@@ -1031,9 +1031,9 @@ mk_mod_usage_info pit hsc_env this_mod direct_imports used_names
 
         (is_direct_import, imp_safe)
             = case lookupModuleEnv direct_imports mod of
-                Just ((_,_,_,safe):_xs) -> (True, safe)
-                Just _                  -> pprPanic "mkUsage: empty direct import" Outputable.empty
-                Nothing                 -> (False, safeImplicitImpsReq dflags)
+                Just ((_,_,_,safe,_,_):_xs) -> (True, safe)
+                Just _                      -> pprPanic "mkUsage: empty direct import" Outputable.empty
+                Nothing                     -> (False, safeImplicitImpsReq dflags)
                 -- Nothing case is for implicit imports like 'System.IO' when 'putStrLn'
                 -- is used in the source code. We require them to be safe in Safe Haskell
 
index a6d2637..410bcc5 100644 (file)
@@ -978,12 +978,12 @@ checkSafeImports dflags tcg_env
 
     condense :: (Module, [ImportedModsVal]) -> Hsc (Module, SrcSpan, IsSafeImport)
     condense (_, [])   = panic "HscMain.condense: Pattern match failure!"
-    condense (m, x:xs) = do (_,_,l,s) <- foldlM cond' x xs
+    condense (m, x:xs) = do (_,_,l,s,_,_) <- foldlM cond' x xs
                             return (m, l, s)
 
     -- ImportedModsVal = (ModuleName, Bool, SrcSpan, IsSafeImport)
     cond' :: ImportedModsVal -> ImportedModsVal -> Hsc ImportedModsVal
-    cond' v1@(m1,_,l1,s1) (_,_,_,s2)
+    cond' v1@(m1,_,l1,s1,_,_) (_,_,_,s2,_,_)
         | s1 /= s2
         = throwErrors $ unitBag $ mkPlainErrMsg dflags l1
               (text "Module" <+> ppr m1 <+>
index 5056f69..9d1427e 100644 (file)
@@ -1029,7 +1029,7 @@ emptyModDetails
 
 -- | Records the modules directly imported by a module for extracting e.g. usage information
 type ImportedMods = ModuleEnv [ImportedModsVal]
-type ImportedModsVal = (ModuleName, Bool, SrcSpan, IsSafeImport)
+type ImportedModsVal = (ModuleName, Bool, SrcSpan, IsSafeImport, Bool, GlobalRdrEnv)
 
 -- | A ModGuts is carried through the compiler, accumulating stuff as it goes
 -- There is only one ModGuts at any time, the one for the module
index 8893fc5..90c856e 100644 (file)
@@ -77,6 +77,7 @@ import DynFlags
 import FastString
 import Control.Monad
 import Data.List
+import Data.Function    ( on )
 import ListSetOps       ( minusList )
 import Constants        ( mAX_TUPLE_SIZE )
 
@@ -1635,9 +1636,11 @@ unboundNameX where_look rdr_name extra
           then addErr err
           else do { local_env  <- getLocalRdrEnv
                   ; global_env <- getGlobalRdrEnv
-                  ; let suggestions = unknownNameSuggestions_ where_look
+                  ; impInfo <- getImports
+                  ; let suggestions1 = unknownNameSuggestions_ where_look
                                          dflags global_env local_env rdr_name
-                  ; addErr (err $$ suggestions) }
+                  ; let suggestions2 = importSuggestions dflags impInfo rdr_name
+                  ; addErr (err $$ suggestions1 $$ suggestions2) }
         ; return (mkUnboundName rdr_name) }
 
 unknownNameErr :: SDoc -> RdrName -> SDoc
@@ -1653,11 +1656,113 @@ type HowInScope = Either SrcSpan ImpDeclSpec
      -- Left loc    =>  locally bound at loc
      -- Right ispec =>  imported as specified by ispec
 
+-- | Generate helpful suggestions if a qualified name Mod.foo is not in scope.
+importSuggestions :: DynFlags -> ImportAvails -> RdrName -> SDoc
+importSuggestions _dflags imports rdr_name
+  | not (isQual rdr_name) = Outputable.empty
+  | null interesting_imports
+  = hsep
+      [ ptext (sLit "No module named")
+      , quotes (ppr mod_name)
+      , ptext (sLit "is imported.")
+      ]
+  | null helpful_imports
+  , [(mod,_)] <- interesting_imports
+  = hsep
+      [ ptext (sLit "Module")
+      , quotes (ppr mod)
+      , ptext (sLit "does not export")
+      , quotes (ppr occ_name) <> dot
+      ]
+  | null helpful_imports
+  , mods <- map fst interesting_imports
+  = hsep
+      [ ptext (sLit "Neither")
+      , quotedListWithNor (map ppr mods)
+      , ptext (sLit "exports")
+      , quotes (ppr occ_name) <> dot
+      ]
+  | [(mod,(_,_,loc,_,_,_))] <- helpful_imports_non_hiding
+  = fsep
+      [ ptext (sLit "Perhaps you want to add")
+      , quotes (ppr occ_name)
+      , ptext (sLit "to the import list")
+      , ptext (sLit "in the import of")
+      , quotes (ppr mod)
+      , parens (ppr loc) <> dot
+      ]
+  | not (null helpful_imports_non_hiding)
+  = fsep
+      [ ptext (sLit "Perhaps you want to add")
+      , quotes (ppr occ_name)
+      , ptext (sLit "to one of these import lists:")
+      ]
+    $$
+    nest 2 (vcat
+        [ quotes (ppr mod) <+> parens (ppr loc)
+        | (mod,(_,_,loc,_,_,_)) <- helpful_imports_non_hiding
+        ])
+  | [(mod,(_,_,loc,_,_,_))] <- helpful_imports_hiding
+  = fsep
+      [ ptext (sLit "Perhaps you want to remove")
+      , quotes (ppr occ_name)
+      , ptext (sLit "from the explicit hiding list")
+      , ptext (sLit "in the import of")
+      , quotes (ppr mod)
+      , parens (ppr loc) <> dot
+      ]
+  | not (null helpful_imports_hiding)
+  = fsep
+      [ ptext (sLit "Perhaps you want to remove")
+      , quotes (ppr occ_name)
+      , ptext (sLit "from the hiding clauses")
+      , ptext (sLit "in one of these imports:")
+      ]
+    $$
+    nest 2 (vcat
+        [ quotes (ppr mod) <+> parens (ppr loc)
+        | (mod,(_,_,loc,_,_,_)) <- helpful_imports_hiding
+        ])
+  | otherwise
+  = Outputable.empty
+ where
+  Just (mod_name, occ_name) = isQual_maybe rdr_name
+
+  -- What import statements provide "Mod" at all
+  interesting_imports = [ (mod, imp)
+    | (mod, mod_imports) <- moduleEnvToList (imp_mods imports)
+    , Just imp <- return $ pick mod_imports
+    ]
+
+  -- We want to keep only one for each original module; preferably one with an
+  -- explicit import list (for no particularly good reason)
+  pick :: [ImportedModsVal] -> Maybe ImportedModsVal
+  pick = listToMaybe . sortBy (compare `on` prefer) . filter select
+    where select (name, _,_,_,_,_) = name == mod_name
+          prefer (_, _, loc, _, hiding, _) = (hiding, loc)
+
+  -- Which of these would export a 'foo'
+  -- (all of these are restricted imports, because if they were not, we
+  -- wouldn't have an out-of-scope error in the first place)
+  helpful_imports = [ (mod, imp)
+    | (mod, imp@(_, _, _, _, _, all_exports)) <- interesting_imports
+    , not . null $ lookupGlobalRdrEnv all_exports occ_name
+    ]
+
+  -- Which of these do that because of an explicit import list
+  helpful_imports_non_hiding = [ (mod, imp)
+    | (mod, imp@(_, _ , _, _, False, _)) <- helpful_imports
+    ]
+
+  -- Which of these do that because of an explicit hiding list
+  helpful_imports_hiding = [ (mod, imp)
+    | (mod, imp@(_, _ , _, _, True, _)) <- helpful_imports
+    ]
+
+-- | Called from the typechecker (TcErrors) when we find an unbound variable
 unknownNameSuggestions :: DynFlags
                        -> GlobalRdrEnv -> LocalRdrEnv
                        -> RdrName -> SDoc
--- Called from the typechecker (TcErrors)
--- when we find an unbound variable
 unknownNameSuggestions = unknownNameSuggestions_ WL_Any
 
 unknownNameSuggestions_ :: WhereLooking -> DynFlags
index 3d26b89..888b8bb 100644 (file)
@@ -264,12 +264,16 @@ rnImportDecl this_mod
     -- filter the imports according to the import declaration
     (new_imp_details, gres) <- filterImports iface imp_spec imp_details
 
+    -- for certain error messages, we’d like to know what could be imported
+    -- here, if everything were imported
+    potential_gres <- mkGlobalRdrEnv . snd <$> filterImports iface imp_spec Nothing
+
     let gbl_env = mkGlobalRdrEnv gres
 
-        -- True <=> import M ()
-        import_all = case imp_details of
-                        Just (is_hiding, L _ ls) -> not is_hiding && null ls
-                        _                    -> False
+        -- import_all == True <=> import M ()
+        (is_hiding, import_all) = case imp_details of
+                        Just (is_hiding, L _ ls) -> (is_hiding, not is_hiding && null ls)
+                        _                        -> (False, False)
 
         -- should the import be safe?
         mod_safe' = mod_safe
@@ -279,7 +283,7 @@ rnImportDecl this_mod
     let imports
           = (calculateAvails dflags iface mod_safe' want_boot) {
                 imp_mods = unitModuleEnv (mi_module iface)
-                            [(qual_mod_name, import_all, loc, mod_safe')] }
+                            [(qual_mod_name, import_all, loc, mod_safe', is_hiding, potential_gres)] }
 
     -- Complain if we import a deprecated module
     whenWOptM Opt_WarnWarningsDeprecations (
@@ -1217,7 +1221,7 @@ exports_from_avail (Just (L _ rdr_items)) rdr_env imports this_mod
 
     imported_modules = [ qual_name
                        | xs <- moduleEnvElts $ imp_mods imports,
-                         (qual_name, _, _, _) <- xs ]
+                         (qual_name, _, _, _, _, _) <- xs ]
 
     exports_from_item :: ExportAccum -> LIE RdrName -> RnM ExportAccum
     exports_from_item acc@(ie_names, occs, exports)
index 6f49563..3116658 100644 (file)
@@ -974,7 +974,7 @@ data ImportAvails
           -- @
           -- it is @Bar@.
           --
-          -- The 'Bool' means:
+          -- The first 'Bool' means:
           --
           --  - @True@ => import was @import Foo ()@
           --
@@ -988,6 +988,8 @@ data ImportAvails
           --
           --   (b) to specify what child modules to initialise
           --
+          -- The second 'Bool' means that the module is safe (see rnImportDecl)
+          --
           -- We need a full ModuleEnv rather than a ModuleNameEnv here,
           -- because we might be importing modules of the same name from
           -- different packages. (currently not the case, but might be in the
index c74f738..db58469 100644 (file)
@@ -17,7 +17,8 @@ module Outputable (
         -- * Pretty printing combinators
         SDoc, runSDoc, initSDocContext,
         docToSDoc,
-        interppSP, interpp'SP, pprQuotedList, pprWithCommas, quotedListWithOr,
+        interppSP, interpp'SP,
+        pprQuotedList, pprWithCommas, quotedListWithOr, quotedListWithNor,
         empty, nest,
         char,
         text, ftext, ptext, ztext,
@@ -910,6 +911,11 @@ quotedListWithOr :: [SDoc] -> SDoc
 quotedListWithOr xs@(_:_:_) = quotedList (init xs) <+> ptext (sLit "or") <+> quotes (last xs)
 quotedListWithOr xs = quotedList xs
 
+quotedListWithNor :: [SDoc] -> SDoc
+-- [x,y,z]  ==>  `x', `y' nor `z'
+quotedListWithNor xs@(_:_:_) = quotedList (init xs) <+> ptext (sLit "nor") <+> quotes (last xs)
+quotedListWithNor xs = quotedList xs
+
 {-
 ************************************************************************
 *                                                                      *
index 1b6a7c2..426d496 100644 (file)
@@ -1,25 +1,31 @@
-\r
-Test10313.hs:9:13: error:\r
-    The deprecation for ‘solverCheckAndGetModel’\r
-      lacks an accompanying binding\r
-\r
-Test10313.hs:15:16: error:\r
-    Multiple warning declarations for ‘Logic’\r
-    also at  Test10313.hs:9:13-17\r
-\r
-Test10313.hs:15:16: error:\r
-    The deprecation for ‘solverCheckAndGetModel’\r
-      lacks an accompanying binding\r
-\r
-Test10313.hs:16:13: error:\r
-    Multiple warning declarations for ‘solverCheckAndGetModel’\r
-    also at  Test10313.hs:10:13-34\r
-\r
-Test10313.hs:30:15: error:\r
-    Not in scope: data constructor ‘Bitstream’\r
-\r
-Test10313.hs:32:7: error: Not in scope: ‘S.concatMap’\r
-\r
-Test10313.hs:32:27: error: Not in scope: ‘GV.stream’\r
-\r
-Test10313.hs:33:7: error: Not in scope: ‘S.sized’\r
+
+Test10313.hs:9:13: error:
+    The deprecation for ‘solverCheckAndGetModel’
+      lacks an accompanying binding
+
+Test10313.hs:15:16: error:
+    Multiple warning declarations for ‘Logic’
+    also at  Test10313.hs:9:13-17
+
+Test10313.hs:15:16: error:
+    The deprecation for ‘solverCheckAndGetModel’
+      lacks an accompanying binding
+
+Test10313.hs:16:13: error:
+    Multiple warning declarations for ‘solverCheckAndGetModel’
+    also at  Test10313.hs:10:13-34
+
+Test10313.hs:30:15: error:
+    Not in scope: data constructor ‘Bitstream’
+
+Test10313.hs:32:7: error:
+    Not in scope: ‘S.concatMap’
+    No module named ‘S’ is imported.
+
+Test10313.hs:32:27: error:
+    Not in scope: ‘GV.stream’
+    No module named ‘GV’ is imported.
+
+Test10313.hs:33:7: error:
+    Not in scope: ‘S.sized’
+    No module named ‘S’ is imported.
index 9d9bc29..0b120e2 100644 (file)
@@ -1,9 +1,15 @@
-\r
-Test10399.hs:10:27: error:\r
-    Not in scope: type constructor or class ‘MPISecret’\r
-\r
-Test10399.hs:12:39: error: Not in scope: ‘P.base’\r
-\r
-Test10399.hs:12:50: error: Not in scope: ‘P.pos’\r
-\r
-Test10399.hs:12:60: error: Not in scope: ‘P.form’\r
+
+Test10399.hs:10:27: error:
+    Not in scope: type constructor or class ‘MPISecret’
+
+Test10399.hs:12:39: error:
+    Not in scope: ‘P.base’
+    No module named ‘P’ is imported.
+
+Test10399.hs:12:50: error:
+    Not in scope: ‘P.pos’
+    No module named ‘P’ is imported.
+
+Test10399.hs:12:60: error:
+    Not in scope: ‘P.form’
+    No module named ‘P’ is imported.
index 68e07ae..663742f 100644 (file)
@@ -1,2 +1,4 @@
 
-<interactive>:1:1: Not in scope: ‘System.IO.hPutStrLn’
+<interactive>:1:1: error:
+    Not in scope: ‘System.IO.hPutStrLn’
+    No module named ‘System.IO’ is imported.
index 2c63d73..ee06e6e 100644 (file)
@@ -1,4 +1,5 @@
 
-<interactive>:1:1:
+<interactive>:1:1: error:
     Not in scope: ‘H.bit’
     Perhaps you meant ‘Q.bit’ (imported from T8639)
+    No module named ‘H’ is imported.
index 0c7de13..5b44b56 100644 (file)
@@ -1,16 +1,18 @@
-\r
-<interactive>:1:1: error: Variable not in scope: nubBy\r
-\r
-<interactive>:1:1: error: Variable not in scope: nub\r
-\r
-<interactive>:1:1: error: Variable not in scope: nubBy\r
-\r
-<interactive>:1:1: error: Variable not in scope: nub\r
-\r
-<interactive>:1:1: error:\r
-    Variable not in scope: nub\r
-    Perhaps you meant ‘L.nub’ (imported from Data.List)\r
-\r
-<interactive>:1:1: error: Not in scope: ‘L.nub’\r
-\r
-<interactive>:1:1: error: Variable not in scope: nub\r
+
+<interactive>:1:1: error: Variable not in scope: nubBy
+
+<interactive>:1:1: error: Variable not in scope: nub
+
+<interactive>:1:1: error: Variable not in scope: nubBy
+
+<interactive>:1:1: error: Variable not in scope: nub
+
+<interactive>:1:1: error:
+    Variable not in scope: nub
+    Perhaps you meant ‘L.nub’ (imported from Data.List)
+
+<interactive>:1:1: error:
+    Not in scope: ‘L.nub’
+    No module named ‘L’ is imported.
+
+<interactive>:1:1: error: Variable not in scope: nub
index d6e6f0e..86c2ffb 100644 (file)
@@ -1,7 +1,9 @@
 
-mod134.hs:6:19:
+mod134.hs:6:19: error:
     Not in scope: ‘Prelude.head’
     Perhaps you meant one of these:
       ‘Prelude.read’ (imported from Prelude),
       ‘Prelude.reads’ (imported from Prelude),
       data constructor ‘Prelude.Left’ (imported from Prelude)
+    Perhaps you want to remove ‘head’ from the explicit hiding list
+    in the import of ‘Prelude’ (mod134.hs:4:1-28).
index 8215ec1..3a6f415 100644 (file)
@@ -1,6 +1,7 @@
 
-mod62.hs:3:9: Qualified name in binding position: M.y
+mod62.hs:3:9: error: Qualified name in binding position: M.y
 
-mod62.hs:3:22:
+mod62.hs:3:22: error:
     Not in scope: ‘M.y’
     Perhaps you meant ‘M.x’ (line 3)
+    No module named ‘M’ is imported.
index d19a032..12dc6b2 100644 (file)
@@ -1,7 +1,8 @@
 
-mod73.hs:3:7:
+mod73.hs:3:7: error:
     Not in scope: ‘Prelude.g’
     Perhaps you meant one of these:
       data constructor ‘Prelude.GT’ (imported from Prelude),
       data constructor ‘Prelude.EQ’ (imported from Prelude),
       data constructor ‘Prelude.LT’ (imported from Prelude)
+    Module ‘Prelude’ does not export ‘g’.
index e366092..55a8ca6 100644 (file)
@@ -1,2 +1,4 @@
 
-mod74.hs:3:7: Not in scope: ‘N.g’
+mod74.hs:3:7: error:
+    Not in scope: ‘N.g’
+    No module named ‘N’ is imported.
index fea1edd..f145350 100644 (file)
@@ -1,2 +1,5 @@
 
-mod88.hs:5:5: Not in scope: data constructor ‘Prelude.Left’
+mod88.hs:5:5: error:
+    Not in scope: data constructor ‘Prelude.Left’
+    Perhaps you want to add ‘Left’ to the import list in the import of
+    ‘Prelude’ (mod88.hs:4:1-30).
index b9dbf7f..01ab869 100644 (file)
@@ -1,2 +1,5 @@
 
-rnfail037.hs:8:7: Not in scope: data constructor ‘Rn037Help.C’
+rnfail037.hs:8:7: error:
+    Not in scope: data constructor ‘Rn037Help.C’
+    Perhaps you want to remove ‘C’ from the explicit hiding list
+    in the import of ‘Rn037Help’ (rnfail037.hs:4:1-28).
index 5d4dc3c..d86f0d1 100644 (file)
@@ -1,2 +1,4 @@
 
-T10781.hs:12:5: error: Not in scope: ‘Foo._name’
+T10781.hs:12:5: error:
+    Not in scope: ‘Foo._name’
+    No module named ‘Foo’ is imported.
diff --git a/testsuite/tests/rename/should_fail/T11071.hs b/testsuite/tests/rename/should_fail/T11071.hs
new file mode 100644 (file)
index 0000000..ad31bc0
--- /dev/null
@@ -0,0 +1,28 @@
+module T11071 where
+
+import Data.List (lines)
+import qualified Data.Map as M ()
+import qualified Data.IntMap as M ()
+import qualified Data.IntMap as M () -- just to see if this confused the code
+
+import qualified Data.Ord as Ord hiding (Down)
+
+import qualified Data.Map as M' hiding (size, filter)
+import qualified Data.Map as M' hiding (size)
+import qualified Data.IntMap as M' hiding (size)
+import qualified System.IO as M' () -- unrelated
+
+ignore :: a -> IO ()
+ignore = const (return ())
+
+main = do
+    ignore NoSuchModule.foo  -- no such module
+    ignore Data.List.foobar  -- does not exist (one import)
+    ignore M.foobar          -- does not exist (two imports)
+    ignore M'.foobar         -- does not exist (three imports)
+    ignore Data.List.sort    -- needs import
+    ignore Data.List.unlines -- needs import, similar to imported
+    ignore M.size            -- multiple modules to import from
+    ignore M.valid           -- only one module to import from
+    ignore Ord.Down          -- explicit hiding
+    ignore M'.size           -- hidden and/or missing in import list
diff --git a/testsuite/tests/rename/should_fail/T11071.stderr b/testsuite/tests/rename/should_fail/T11071.stderr
new file mode 100644 (file)
index 0000000..e3d5e30
--- /dev/null
@@ -0,0 +1,53 @@
+
+T11071.hs:19:12: error:
+    Not in scope: ‘NoSuchModule.foo’
+    No module named ‘NoSuchModule’ is imported.
+
+T11071.hs:20:12: error:
+    Not in scope: ‘Data.List.foobar’
+    Module ‘Data.List’ does not export ‘foobar’.
+
+T11071.hs:21:12: error:
+    Not in scope: ‘M.foobar’
+    Neither ‘Data.Map’ nor ‘Data.IntMap’ exports ‘foobar’.
+
+T11071.hs:22:12: error:
+    Not in scope: ‘M'.foobar’
+    Neither ‘Data.Map’, ‘Data.IntMap’ nor ‘System.IO’ exports ‘foobar’.
+
+T11071.hs:23:12: error:
+    Not in scope: ‘Data.List.sort’
+    Perhaps you want to add ‘sort’ to the import list in the import of
+    ‘Data.List’ (T11071.hs:3:1-24).
+
+T11071.hs:24:12: error:
+    Not in scope: ‘Data.List.unlines’
+    Perhaps you meant ‘Data.List.lines’ (imported from Data.List)
+    Perhaps you want to add ‘unlines’ to the import list
+    in the import of ‘Data.List’ (T11071.hs:3:1-24).
+
+T11071.hs:25:12: error:
+    Not in scope: ‘M.size’
+    Perhaps you want to add ‘size’ to one of these import lists:
+      ‘Data.Map’ (T11071.hs:4:1-33)
+      ‘Data.IntMap’ (T11071.hs:5:1-36)
+
+T11071.hs:26:12: error:
+    Not in scope: ‘M.valid’
+    Perhaps you meant one of these:
+      ‘M'.valid’ (imported from Data.Map),
+      ‘M'.valid’ (imported from Data.Map)
+    Perhaps you want to add ‘valid’ to the import list in the import of
+    ‘Data.Map’ (T11071.hs:4:1-33).
+
+T11071.hs:27:12: error:
+    Not in scope: data constructor ‘Ord.Down’
+    Perhaps you want to remove ‘Down’ from the explicit hiding list
+    in the import of ‘Data.Ord’ (T11071.hs:8:1-46).
+
+T11071.hs:28:12: error:
+    Not in scope: ‘M'.size’
+    Perhaps you want to remove ‘size’ from the hiding clauses
+    in one of these imports:
+      ‘Data.Map’ (T11071.hs:10:1-53)
+      ‘Data.IntMap’ (T11071.hs:12:1-48)
index b240139..d5a2247 100644 (file)
@@ -1,4 +1,7 @@
 
-T2901.hs:6:5: Not in scope: data constructor ‘F.Foo’
+T2901.hs:6:5: error:
+    Not in scope: data constructor ‘F.Foo’
+    No module named ‘F’ is imported.
 
-T2901.hs:6:13: ‘F.field’ is not a (visible) constructor field name
+T2901.hs:6:13: error:
+    ‘F.field’ is not a (visible) constructor field name
index aa5f870..5663b90 100644 (file)
@@ -1,5 +1,7 @@
 
-T5657.hs:3:8: Not in scope: ‘LT..’
+T5657.hs:3:8: error:
+    Not in scope: ‘LT..’
+    No module named ‘LT’ is imported.
 
-T5657.hs:3:8:
+T5657.hs:3:8: error:
     A section must be enclosed in parentheses thus: (LT.. GT)
index 994ea78..0f93c21 100644 (file)
@@ -1,2 +1,4 @@
 
-T5892b.hs:11:7: Not in scope: ‘T5892b.subForest’
+T5892b.hs:11:7: error:
+    Not in scope: ‘T5892b.subForest’
+    No module named ‘T5892b’ is imported.
index 48814ec..66dfeaa 100644 (file)
@@ -138,3 +138,4 @@ test('T10618', normal, compile_fail, [''])
 test('T10668', normal, compile_fail, [''])
 test('T5001b', normal, compile_fail, [''])
 test('T10781', normal, compile_fail, [''])
+test('T11071', normal, compile_fail, [''])
index 5b2cd36..462dc5f 100644 (file)
@@ -1,2 +1,5 @@
 
-rnfail030.hs:2:21: Not in scope: ‘Data.List.map’
+rnfail030.hs:2:21: error:
+    Not in scope: ‘Data.List.map’
+    Perhaps you want to add ‘map’ to the import list in the import of
+    ‘Data.List’ (rnfail030.hs:3:1-19).
index 828d512..95d8ea1 100644 (file)
@@ -1,2 +1,5 @@
 
-rnfail031.hs:2:21: Not in scope: ‘Data.List.map’
+rnfail031.hs:2:21: error:
+    Not in scope: ‘Data.List.map’
+    Perhaps you want to add ‘map’ to the import list in the import of
+    ‘Data.List’ (rnfail031.hs:3:1-36).
index 2169fd5..70d80a0 100644 (file)
@@ -1,7 +1,9 @@
 
-rnfail032.hs:2:21:
+rnfail032.hs:2:21: error:
     Not in scope: ‘Data.List.map’
     Perhaps you meant one of these:
       ‘Data.List.zip’ (imported from Data.List),
       ‘Data.List.all’ (imported from Data.List),
       ‘Data.List.and’ (imported from Data.List)
+    Perhaps you want to remove ‘map’ from the explicit hiding list
+    in the import of ‘Data.List’ (rnfail032.hs:3:1-41).
index 6b6849d..277b42f 100644 (file)
@@ -1,7 +1,9 @@
 
-rnfail033.hs:2:21:
+rnfail033.hs:2:21: error:
     Not in scope: ‘Data.List.map’
     Perhaps you meant one of these:
       ‘Data.List.zip’ (imported from Data.List),
       ‘Data.List.all’ (imported from Data.List),
       ‘Data.List.and’ (imported from Data.List)
+    Perhaps you want to remove ‘map’ from the explicit hiding list
+    in the import of ‘Data.List’ (rnfail033.hs:3:1-31).
index 78bc649..63e6eb5 100644 (file)
@@ -1,6 +1,7 @@
 
-rnfail034.hs:4:11: Qualified name in binding position: M.y
+rnfail034.hs:4:11: error: Qualified name in binding position: M.y
 
-rnfail034.hs:4:26:
+rnfail034.hs:4:26: error:
     Not in scope: ‘M.y’
     Perhaps you meant ‘M.g’ (line 4)
+    No module named ‘M’ is imported.
index 5d70969..a0dc5c3 100644 (file)
@@ -1,8 +1,9 @@
-\r
-<interactive>:5:9: error:\r
-    Not in scope: ‘System.IO.Unsafe.unsafePerformIO’\r
-\r
-<interactive>:6:9: error:\r
-    Variable not in scope: x :: IO Integer -> t\r
-\r
-<interactive>:7:1: error: Variable not in scope: y\r
+
+<interactive>:5:9: error:
+    Not in scope: ‘System.IO.Unsafe.unsafePerformIO’
+    No module named ‘System.IO.Unsafe’ is imported.
+
+<interactive>:6:9: error:
+    Variable not in scope: x :: IO Integer -> t
+
+<interactive>:7:1: error: Variable not in scope: y