Skip to content

Commit 848e209

Browse files
mpickeringMikolaj
authored andcommitted
Fix Monoid instances for ForeignLib & Executable
The Semigroup and Monoid instances for ForeignLib were completely broken: for the `foreignLibVersionInfo` and `foreignLibVersionInfo`, we essentially had the following: mempty :: Maybe XYZ mempty = Nothing (<>) :: Maybe XYZ -> Maybe XYZ -> Maybe XYZ _ <> b = b which is obviously not a valid Monoid, as `Just x <> Nothing = Nothing`, violating the identity law. The Semigroup instance for Executable was also deeply suspicious, as it combined the module paths, which makes no sense. Now we instead error if the two module paths are different (and both nonempty).
1 parent feb5a0b commit 848e209

File tree

3 files changed

+17
-15
lines changed

3 files changed

+17
-15
lines changed

Cabal-syntax/src/Distribution/Types/Executable.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ instance Semigroup Executable where
4141
a <> b =
4242
Executable
4343
{ exeName = combineNames a b exeName "executable"
44-
, modulePath = combine modulePath
44+
, modulePath = combineNames a b modulePath "modulePath"
4545
, exeScope = combine exeScope
4646
, buildInfo = combine buildInfo
4747
}

Cabal-syntax/src/Distribution/Types/ForeignLib.hs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import Distribution.Types.ForeignLibType
2828
import Distribution.Types.UnqualComponentName
2929
import Distribution.Version
3030

31+
import Data.Monoid
3132
import qualified Distribution.Compat.CharParsing as P
3233
import qualified Text.PrettyPrint as Disp
3334
import qualified Text.Read as Read
@@ -144,13 +145,14 @@ instance Semigroup ForeignLib where
144145
, foreignLibType = combine foreignLibType
145146
, foreignLibOptions = combine foreignLibOptions
146147
, foreignLibBuildInfo = combine foreignLibBuildInfo
147-
, foreignLibVersionInfo = combine'' foreignLibVersionInfo
148-
, foreignLibVersionLinux = combine'' foreignLibVersionLinux
148+
, foreignLibVersionInfo = chooseLast foreignLibVersionInfo
149+
, foreignLibVersionLinux = chooseLast foreignLibVersionLinux
149150
, foreignLibModDefFile = combine foreignLibModDefFile
150151
}
151152
where
152153
combine field = field a `mappend` field b
153-
combine'' field = field b
154+
-- chooseLast: the second field overrides the first, unless it is Nothing
155+
chooseLast field = getLast (Last (field a) <> Last (field b))
154156

155157
instance Monoid ForeignLib where
156158
mempty =

Cabal-syntax/src/Distribution/Types/UnqualComponentName.hs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ module Distribution.Types.UnqualComponentName
1414

1515
import Distribution.Compat.Prelude
1616
import Distribution.Utils.ShortText
17-
import Prelude as P (null)
1817

1918
import Distribution.Parsec
2019
import Distribution.Pretty
@@ -111,28 +110,29 @@ unqualComponentNameToPackageName = mkPackageNameST . unUnqualComponentNameST
111110
-- (partial function).
112111
-- Useful in 'Semigroup' and similar instances.
113112
combineNames
114-
:: a
113+
:: (Monoid b, Eq b, Show b)
114+
=> a
115115
-> a
116-
-> (a -> UnqualComponentName)
116+
-> (a -> b)
117117
-> String
118-
-> UnqualComponentName
118+
-> b
119119
combineNames a b tacc tt
120120
-- One empty or the same.
121-
| P.null unb
122-
|| una == unb =
121+
| nb == mempty
122+
|| na == nb =
123123
na
124-
| P.null una = nb
124+
| na == mempty =
125+
nb
125126
-- Both non-empty, different.
126127
| otherwise =
127128
error $
128129
"Ambiguous values for "
129130
++ tt
130131
++ " field: '"
131-
++ una
132+
++ show na
132133
++ "' and '"
133-
++ unb
134+
++ show nb
134135
++ "'"
135136
where
136137
(na, nb) = (tacc a, tacc b)
137-
una = unUnqualComponentName na
138-
unb = unUnqualComponentName nb
138+
{-# INLINEABLE combineNames #-}

0 commit comments

Comments
 (0)