Make the order of fixities in the iface file deterministic
authorBartosz Nitka <bnitka@fb.com>
Wed, 2 Dec 2015 11:28:13 +0000 (03:28 -0800)
committerBartosz Nitka <bnitka@fb.com>
Wed, 2 Dec 2015 11:29:14 +0000 (03:29 -0800)
This normalizes the order of written fixities by sorting by
`OccName` making it independent of `Unique` order.

Test Plan: I've added a new testcase

Reviewers: austin, bgamari, simonmar

Reviewed By: simonmar

Subscribers: thomie

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

GHC Trac Issues: #4012

compiler/iface/MkIface.hs
testsuite/tests/determinism/determ010/A.hs [new file with mode: 0644]
testsuite/tests/determinism/determ010/Makefile [new file with mode: 0644]
testsuite/tests/determinism/determ010/all.T [new file with mode: 0644]
testsuite/tests/determinism/determ010/determ010.stdout [new file with mode: 0644]

index d955fa5..e428b58 100644 (file)
@@ -222,7 +222,11 @@ mkIface_ hsc_env maybe_old_fingerprint
                    nameIsLocalOrFrom this_mod name  ]
                       -- Sigh: see Note [Root-main Id] in TcRnDriver
 
-        fixities    = [(occ,fix) | FixItem occ fix <- nameEnvElts fix_env]
+        fixities    = sortBy (comparing fst)
+          [(occ,fix) | FixItem occ fix <- nameEnvElts fix_env]
+          -- The order of fixities returned from nameEnvElts is not
+          -- deterministic, so we sort by OccName to canonicalize it.
+          -- See Note [Deterministic UniqFM] in UniqDFM for more details.
         warns       = src_warns
         iface_rules = map coreRuleToIfaceRule rules
         iface_insts = map instanceToIfaceInst $ fixSafeInstances safe_mode insts
diff --git a/testsuite/tests/determinism/determ010/A.hs b/testsuite/tests/determinism/determ010/A.hs
new file mode 100644 (file)
index 0000000..b60f90a
--- /dev/null
@@ -0,0 +1,17 @@
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+module ShouldCompile where
+
+-- tests deterministic order of fixities in the interface file
+
+infixl 1 `f`
+infixr 2 \\\
+infix  3 :==>
+infix  4 `MkFoo`
+
+data Foo = MkFoo Int | Float :==> Double
+
+f :: a -> b -> a
+x `f` y = x
+
+(\\\) :: (Eq a) => [a] -> [a] -> [a]
+(\\\) xs ys =  xs
diff --git a/testsuite/tests/determinism/determ010/Makefile b/testsuite/tests/determinism/determ010/Makefile
new file mode 100644 (file)
index 0000000..1f12622
--- /dev/null
@@ -0,0 +1,13 @@
+TOP=../../..
+include $(TOP)/mk/boilerplate.mk
+include $(TOP)/mk/test.mk
+
+TEST_HC_OPTS_NO_RECOMP = $(filter-out -fforce-recomp,$(TEST_HC_OPTS))
+
+determ010:
+       $(RM) A.hi A.o
+       '$(TEST_HC)' $(TEST_HC_OPTS_NO_RECOMP) -dinitial-unique=0 -dunique-increment=1 A.hs
+       $(CP) A.hi A.normal.hi
+       $(RM) A.hi A.o
+       '$(TEST_HC)' $(TEST_HC_OPTS_NO_RECOMP) -dinitial-unique=16777215 -dunique-increment=-1 A.hs
+       diff A.hi A.normal.hi
diff --git a/testsuite/tests/determinism/determ010/all.T b/testsuite/tests/determinism/determ010/all.T
new file mode 100644 (file)
index 0000000..030868f
--- /dev/null
@@ -0,0 +1,4 @@
+test('determ010',
+     extra_clean(['A.o', 'A.hi', 'A.normal.hi']),
+     run_command,
+     ['$MAKE -s --no-print-directory determ010'])
diff --git a/testsuite/tests/determinism/determ010/determ010.stdout b/testsuite/tests/determinism/determ010/determ010.stdout
new file mode 100644 (file)
index 0000000..9a2bb82
--- /dev/null
@@ -0,0 +1,2 @@
+[1 of 1] Compiling ShouldCompile    ( A.hs, A.o )
+[1 of 1] Compiling ShouldCompile    ( A.hs, A.o )