git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Fix cycles being detected with qualified imports
9a6bcb3Gary Burgess
examples/passing/2018.pursnew file+25
@@ -0,0 +1,25 @@
1+module B where
2+
3+ data Foo = X | Y
4+
5+module A where
6+
7+ import B as Main
8+
9+ -- Prior to the 2018 fix this would be detected as a cycle between A and Main.
10+ foo ∷ Main.Foo → Main.Foo
11+ foo x = x
12+
13+module Main where
14+
15+import Prelude
16+import A (foo)
17+import B (Foo(..))
18+import Control.Monad.Eff (Eff)
19+import Control.Monad.Eff.Console (CONSOLE, log)
20+
21+main :: forall e. Eff (console :: CONSOLE | e) Unit
22+main = do
23+ let tmp = foo X
24+ log "Done"
25+
src/Language/PureScript/ModuleDependencies.hs+37−24
@@ -1,19 +1,8 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.ModuleDependencies
4−-- Copyright : (c) 2013-15 Phil Freeman, (c) 2014-15 Gary Burgess
5−-- License : MIT (http://opensource.org/licenses/MIT)
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- | Provides the ability to sort modules based on module dependencies
12−--
13−-----------------------------------------------------------------------------
14−
15{-# LANGUAGE FlexibleContexts #-}
1{-# LANGUAGE FlexibleContexts #-}
16
2
3+-- |
4+-- Provides the ability to sort modules based on module dependencies
5+--
17module Language.PureScript.ModuleDependencies (
6module Language.PureScript.ModuleDependencies (
18 sortModules,
7 sortModules,
19 ModuleGraph
8 ModuleGraph
@@ -40,7 +29,7 @@ type ModuleGraph = [(ModuleName, [ModuleName])]
40--
29--
41sortModules :: (MonadError MultipleErrors m) => [Module] -> m ([Module], ModuleGraph)
30sortModules :: (MonadError MultipleErrors m) => [Module] -> m ([Module], ModuleGraph)
42sortModules ms = do
31sortModules ms = do
43− let verts = map (\m@(Module _ _ _ ds _) -> (m, getModuleName m, nub (concatMap usedModules ds))) ms
32+ let verts = map goModule ms
44 ms' <- mapM toModule $ stronglyConnComp verts
33 ms' <- mapM toModule $ stronglyConnComp verts
45 let (graph, fromVertex, toVertex) = graphFromEdges verts
34 let (graph, fromVertex, toVertex) = graphFromEdges verts
46 moduleGraph = do (_, mn, _) <- verts
35 moduleGraph = do (_, mn, _) <- verts
@@ -49,29 +38,53 @@ sortModules ms = do
49 toKey i = case fromVertex i of (_, key, _) -> key
38 toKey i = case fromVertex i of (_, key, _) -> key
50 return (mn, filter (/= mn) (map toKey deps))
39 return (mn, filter (/= mn) (map toKey deps))
51 return (ms', moduleGraph)
40 return (ms', moduleGraph)
41+ where
42+ goModule :: Module -> (Module, ModuleName, [ModuleName])
43+ goModule m@(Module _ _ _ ds _) =
44+ let ams = concatMap extractQualAs ds
45+ in (m, getModuleName m, nub (concatMap (usedModules ams) ds))
46+
47+ -- Extract module names that have been brought into scope by an `as` import.
48+ extractQualAs :: Declaration -> [ModuleName]
49+ extractQualAs (PositionedDeclaration _ _ d) = extractQualAs d
50+ extractQualAs (ImportDeclaration _ _ (Just am) _) = [am]
51+ extractQualAs _ = []
52
52
53-- |
53-- |
54−-- Calculate a list of used modules based on explicit imports and qualified names
54+-- Calculate a list of used modules based on explicit imports and qualified
55+-- names. `ams` is a list of `ModuleNames` that refer to names brought into
56+-- scope by importing with `as` - this ensures that when building the list we
57+-- don't inadvertantly assume a dependency on an actual module, if there is a
58+-- module that has the same name as the qualified import.
55--
59--
56−usedModules :: Declaration -> [ModuleName]
60+usedModules :: [ModuleName] -> Declaration -> [ModuleName]
57−usedModules d =
61+usedModules ams d =
58 let (f, _, _, _, _) = everythingOnValues (++) forDecls forValues (const []) (const []) (const [])
62 let (f, _, _, _, _) = everythingOnValues (++) forDecls forValues (const []) (const []) (const [])
59 (g, _, _, _, _) = accumTypes (everythingOnTypes (++) forTypes)
63 (g, _, _, _, _) = accumTypes (everythingOnTypes (++) forTypes)
60 in nub (f d ++ g d)
64 in nub (f d ++ g d)
61 where
65 where
66+
62 forDecls :: Declaration -> [ModuleName]
67 forDecls :: Declaration -> [ModuleName]
63− forDecls (ImportDeclaration mn _ _ _) = [mn]
68+ forDecls (ImportDeclaration mn _ _ _) =
69+ -- Regardless of whether an imported module is qualified we still need to
70+ -- take into account its import to build an accurate list of dependencies.
71+ [mn]
64− forDecls (FixityDeclaration _ _ (Just (Qualified (Just mn) _))) = [mn]
72+ forDecls (FixityDeclaration _ _ (Just (Qualified (Just mn) _)))
73+ | mn `notElem` ams = [mn]
65− forDecls (TypeInstanceDeclaration _ _ (Qualified (Just mn) _) _ _) = [mn]
74+ forDecls (TypeInstanceDeclaration _ _ (Qualified (Just mn) _) _ _)
75+ | mn `notElem` ams = [mn]
66 forDecls _ = []
76 forDecls _ = []
67
77
68 forValues :: Expr -> [ModuleName]
78 forValues :: Expr -> [ModuleName]
69− forValues (Var (Qualified (Just mn) _)) = [mn]
79+ forValues (Var (Qualified (Just mn) _))
80+ | mn `notElem` ams = [mn]
70− forValues (Constructor (Qualified (Just mn) _)) = [mn]
81+ forValues (Constructor (Qualified (Just mn) _))
82+ | mn `notElem` ams = [mn]
71 forValues _ = []
83 forValues _ = []
72
84
73 forTypes :: Type -> [ModuleName]
85 forTypes :: Type -> [ModuleName]
74− forTypes (TypeConstructor (Qualified (Just mn) _)) = [mn]
86+ forTypes (TypeConstructor (Qualified (Just mn) _))
87+ | mn `notElem` ams = [mn]
75 forTypes _ = []
88 forTypes _ = []
76
89
77-- |
90-- |