@@ -58,7 +58,7 @@ createBindingGroups moduleName ds = do
58 dataBindingGroupDecls <- mapM toDataBindingGroup $ stronglyConnComp dataVerts
58 dataBindingGroupDecls <- mapM toDataBindingGroup $ stronglyConnComp dataVerts
59 let allIdents = map getIdent values
59 let allIdents = map getIdent values
60 valueVerts = map (\d -> (d, getIdent d, usedIdents moduleName d `intersect` allIdents)) values
60 valueVerts = map (\d -> (d, getIdent d, usedIdents moduleName d `intersect` allIdents)) values
61− bindingGroupDecls = map toBindingGroup $ stronglyConnComp valueVerts
61+ bindingGroupDecls <- mapM (toBindingGroup moduleName) $ stronglyConnComp valueVerts
62 return $ filter isImportDecl ds ++
62 return $ filter isImportDecl ds ++
63 filter isExternDataDecl ds ++
63 filter isExternDataDecl ds ++
64 filter isExternInstanceDecl ds ++
64 filter isExternInstanceDecl ds ++
@@ -107,6 +107,19 @@ usedIdents moduleName =
107 usedNamesB :: S.Set Ident -> Binder -> (S.Set Ident, [Ident])
107 usedNamesB :: S.Set Ident -> Binder -> (S.Set Ident, [Ident])
108 usedNamesB scope binder = (scope `S.union` S.fromList (binderNames binder), [])
108 usedNamesB scope binder = (scope `S.union` S.fromList (binderNames binder), [])
110+usedImmediateIdents :: ModuleName -> Declaration -> [Ident]
111+usedImmediateIdents moduleName =
112+ let (f, _, _, _, _) = everythingWithContextOnValues True [] (++) def usedNamesE def def def
117+ usedNamesE :: Bool -> Expr -> (Bool, [Ident])
118+ usedNamesE True (Var (Qualified Nothing name)) = (True, [name])
119+ usedNamesE True (Var (Qualified (Just moduleName') name)) | moduleName == moduleName' = (True, [name])
120+ usedNamesE True (Abs _ _) = (False, [])
121+ usedNamesE scope _ = (scope, [])
110usedProperNames :: ModuleName -> Declaration -> [ProperName]
123usedProperNames :: ModuleName -> Declaration -> [ProperName]
111usedProperNames moduleName =
124usedProperNames moduleName =
112 let (f, _, _, _, _) = accumTypes (everythingOnTypes (++) usedNames)
125 let (f, _, _, _, _) = accumTypes (everythingOnTypes (++) usedNames)
@@ -131,10 +144,34 @@ getProperName (TypeSynonymDeclaration pn _ _) = pn
131getProperName (PositionedDeclaration _ d) = getProperName d
144getProperName (PositionedDeclaration _ d) = getProperName d
132getProperName _ = error "Expected DataDeclaration"
145getProperName _ = error "Expected DataDeclaration"
148+-- Convert a group of mutually-recursive dependencies into a BindingGroupDeclaration (or simple ValueDeclaration).
134−toBindingGroup :: SCC Declaration -> Declaration
151+toBindingGroup :: ModuleName -> SCC Declaration -> Either ErrorStack Declaration
135−toBindingGroup (AcyclicSCC d) = d
152+toBindingGroup _ (AcyclicSCC d) = return d
136−toBindingGroup (CyclicSCC [d]) = d
153+toBindingGroup _ (CyclicSCC [d]) = return d
137−toBindingGroup (CyclicSCC ds') = BindingGroupDeclaration $ map fromValueDecl ds'
154+toBindingGroup moduleName (CyclicSCC ds') =
155+ -- Once we have a mutually-recursive group of declarations, we need to sort
156+ -- them further by their immediate dependencies (those outside function
157+ -- bodies). In particular, this is relevant for type instance dictionaries
158+ -- whose members require other type instances (for example, functorEff
159+ -- defines (<$>) = liftA1, which depends on applicativeEff). Note that
160+ -- superclass references are still inside functions, so don't count here.
161+ -- If we discover declarations that still contain mutually-recursive
162+ -- immediate references, we're guaranteed to get an undefined reference at
163+ -- runtime, so treat this as an error. See also github issue #365.
164+ BindingGroupDeclaration <$> mapM toBinding (stronglyConnComp valueVerts)
167+ idents = map (\(_, i, _) -> i) valueVerts
169+ valueVerts :: [(Declaration, Ident, [Ident])]
170+ valueVerts = map (\d -> (d, getIdent d, usedImmediateIdents moduleName d `intersect` idents)) ds'
172+ toBinding :: SCC Declaration -> Either ErrorStack (Ident, NameKind, Expr)
173+ toBinding (AcyclicSCC d) = return $ fromValueDecl d
174+ toBinding (CyclicSCC ds) = Left $ mkErrorStack ("Cycle in value declarations " ++ unwords (map (show . getIdent) ds)) Nothing
139toDataBindingGroup :: SCC Declaration -> Either ErrorStack Declaration
176toDataBindingGroup :: SCC Declaration -> Either ErrorStack Declaration
140toDataBindingGroup (AcyclicSCC d) = return d
177toDataBindingGroup (AcyclicSCC d) = return d