Skip to content

Commit 8f9bc92

Browse files
authored
ExternsDiff: compute deps of TypeSynonyms properly (#7)
Fixes a bug where type synonym changes are incorrectly computed when diffing externs. See https://github.com/zyla/purs-recompilation-repro for a reproducer of the bug. Bug explanation: Externs files can have multiple entries with the same Ref, but the code in ExternsDiff assumed uniqueness. This led to buggy dependency graph construction. The fix is to merge duplicate entries.
1 parent c492385 commit 8f9bc92

File tree

1 file changed

+10
-8
lines changed

1 file changed

+10
-8
lines changed

src/Language/PureScript/Make/ExternsDiff.hs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -354,19 +354,21 @@ isEmpty (ExternsDiff _ refs)
354354
type Tuple4 m a = (m a, m a, m a, m a)
355355

356356
-- | Returns refs as a tuple of four (added, removed, changed, unchanged).
357-
splitRefs :: Ord r => Eq a => [a] -> [a] -> (a -> Maybe r) -> Tuple4 [] r
357+
splitRefs :: forall ref a deps. Monoid deps => Ord ref => Eq a => [a] -> [a] -> (a -> Maybe (ref, deps)) -> Tuple4 [] (ref, deps)
358358
splitRefs new old toRef =
359359
M.foldrWithKey go (added, [], [], []) oldMap
360360
where
361-
toMap = M.fromList . mapMaybe (((<$>) . flip (,)) <*> toRef)
361+
toMap :: [a] -> Map ref (deps, [a])
362+
toMap = M.fromListWith (<>) . mapMaybe (\decl -> do (ref, deps) <- toRef decl; pure (ref, (deps, [decl])))
362363
newMap = toMap new
363364
oldMap = toMap old
364-
added = M.keys $ M.difference newMap oldMap
365-
go ref decl (a, r, c, u) = case M.lookup ref newMap of
366-
Nothing -> (a, r <> [ref], c, u)
367-
Just newDecl
368-
| decl /= newDecl -> (a, r, ref : c, u)
369-
| otherwise -> (a, r, c, ref : u)
365+
added = fmap (\(ref, (deps, _)) -> (ref, deps)) $ M.toList $ M.difference newMap oldMap
366+
go :: ref -> (deps, [a]) -> Tuple4 [] (ref, deps) -> Tuple4 [] (ref, deps)
367+
go ref (deps, decls) (a, r, c, u) = case M.lookup ref newMap of
368+
Nothing -> (a, r <> [(ref, deps)], c, u)
369+
Just (_, newDecls)
370+
| decls /= newDecls -> (a, r, (ref, deps) : c, u)
371+
| otherwise -> (a, r, c, (ref, deps) : u)
370372

371373
-- | Traverses the type and finds all the refs within.
372374
typeDeps :: P.Type a -> S.Set (ModuleName, Ref)

0 commit comments

Comments
 (0)