|
|
[[_TOC_]]
|
|
|
|
|
|
# GHC 8.0.x Migration Guide
|
|
|
|
|
|
|
... | ... | @@ -31,11 +33,14 @@ In previous versions of GHC, it was possible to hide an impredicative type behin |
|
|
The compiler is now a bit more conservative in solving constraints previously
|
|
|
provided by superclasses (see [\#11762](https://gitlab.haskell.org//ghc/ghc/issues/11762)). For instance, consider this program,
|
|
|
|
|
|
```
|
|
|
{-# LANGUAGE FlexibleInstances #-}{-# LANGUAGE UndecidableInstances #-}classSuper a
|
|
|
class(Super a)=>Left a
|
|
|
class(Super a)=>Right a
|
|
|
instance(Left a)=>Right a -- this is now an error
|
|
|
```hs
|
|
|
{-# LANGUAGE FlexibleInstances #-}
|
|
|
{-# LANGUAGE UndecidableInstances #-}
|
|
|
|
|
|
class Super a
|
|
|
class (Super a) => Left a
|
|
|
class (Super a) => Right a
|
|
|
instance (Left a) => Right a -- this is now an error
|
|
|
```
|
|
|
|
|
|
|
... | ... | @@ -45,8 +50,8 @@ previous releases, which would accept this declaration, using the `Super a` |
|
|
constraint implied by the `Left a` constraint. To fix this simply add the
|
|
|
needed superclass constraint explicitly,
|
|
|
|
|
|
```
|
|
|
instance(Left a,Super a)=>Right a
|
|
|
```hs
|
|
|
instance (Left a, Super a) => Right a
|
|
|
```
|
|
|
|
|
|
### `-fwarn-pointless-pragmas`
|
... | ... | @@ -59,10 +64,14 @@ This flag has been removed and replaced by two flags `-Wmissed-specialisations` |
|
|
|
|
|
The old syntax for record constructors for a GADT has been removed
|
|
|
|
|
|
```
|
|
|
-- Old SyntaxdataG2 a ::*whereG2A{ g2a :: a, g2b ::Int}::G2 a
|
|
|
```hs
|
|
|
-- Old Syntax
|
|
|
data G2 a :: * where
|
|
|
G2A { g2a :: a, g2b :: Int } :: G2 a
|
|
|
|
|
|
-- New SyntaxdataG2 a ::*whereG2A::{ g2a :: a, g2b ::Int}->G2 a
|
|
|
-- New Syntax
|
|
|
data G2 a :: * where
|
|
|
G2A :: { g2a :: a, g2b :: Int } -> G2 a
|
|
|
|
|
|
```
|
|
|
|
... | ... | @@ -74,8 +83,12 @@ This flag was widely regarded as a misfeature, in prior versions it issued a dep |
|
|
|
|
|
The old syntax which allowed quotes to be prefixed by `$` has been removed.
|
|
|
|
|
|
```
|
|
|
-- Old Syntaxfoo=[$x|...]-- New Syntaxfoo=[x|...]
|
|
|
```hs
|
|
|
-- Old Syntax
|
|
|
foo = [$x| ... ]
|
|
|
|
|
|
-- New Syntax
|
|
|
foo = [x| ... ]
|
|
|
```
|
|
|
|
|
|
### Kind-level definitions shuffled around
|
... | ... | @@ -87,27 +100,31 @@ If you're using various bits of magic from within GHC and importing from `GHC.Pr |
|
|
|
|
|
1. The ordering of the constraints has been changed so that required constraints appear before provided constraints.
|
|
|
|
|
|
1. A single set of constraints corresponds to a set of required rather than provided constraints.
|
|
|
2. A single set of constraints corresponds to a set of required rather than provided constraints.
|
|
|
|
|
|
|
|
|
For example:
|
|
|
|
|
|
```
|
|
|
--beforepatternP1:: prov => req => ty
|
|
|
```hs
|
|
|
--before
|
|
|
|
|
|
pattern P1 :: prov => req => ty
|
|
|
|
|
|
patternP2:: prov => ty
|
|
|
pattern P2 :: prov => ty
|
|
|
|
|
|
patternP3::()=> req => ty
|
|
|
pattern P3 :: () => req => ty
|
|
|
|
|
|
patternP4:: ty
|
|
|
pattern P4 :: ty
|
|
|
|
|
|
-- after
|
|
|
|
|
|
|
|
|
pattern P1 :: req => prov => ty
|
|
|
|
|
|
|
|
|
pattern P2 :: () => prov => ty
|
|
|
|
|
|
|
|
|
pattern P3 :: req => ty
|
|
|
|
|
|
pattern P4 :: ty
|
|
|
|
|
|
```
|
|
|
|
... | ... | @@ -121,7 +138,7 @@ patternP4:: ty |
|
|
|
|
|
**TLDR**: The gist of the following paragraphs is to add some variation of the following snippet to your `.cabal` file, and address the warnings emitted by GHC when compiling your package:
|
|
|
|
|
|
```wiki
|
|
|
```
|
|
|
if impl(ghc >= 8.0)
|
|
|
ghc-options: -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances
|
|
|
else
|
... | ... | @@ -135,44 +152,37 @@ The following suggestions are not mandatory but recommended for those who wish t |
|
|
<table><tr><th>Normalise `Applicative`/`Monad` instance definitions</th>
|
|
|
<td></td></tr></table>
|
|
|
|
|
|
> `base-4.9.0.0` continues to generalise functions from `Monad` to `Applicative`. However, in order to avoid performance regressions due to sub-optimally defined `Applicative`/`Monad` instances, it's highly advised to follow the
|
|
|
> [AMP+MRP refactoring guidelines ](migration/7.10#)
|
|
|
> that were already provided in the [GHC 7.10.x Migration Guide](migration/7.10).
|
|
|
`base-4.9.0.0` continues to generalise functions from `Monad` to `Applicative`. However, in order to avoid performance regressions due to sub-optimally defined `Applicative`/`Monad` instances, it's highly advised to follow the
|
|
|
[AMP+MRP refactoring guidelines ](migration/7.10#)
|
|
|
that were already provided in the [GHC 7.10.x Migration Guide](migration/7.10).
|
|
|
|
|
|
>
|
|
|
> A new warning that needs to be enabled via `-Wnoncanonical-monad-instances` (not implied by `-Wcompat`) is available to help detect code which may be at risk.
|
|
|
A new warning that needs to be enabled via `-Wnoncanonical-monad-instances` (not implied by `-Wcompat`) is available to help detect code which may be at risk.
|
|
|
|
|
|
<table><tr><th>Provide `Semigroup`/`Monoid` instances definitions</th>
|
|
|
<td></td></tr></table>
|
|
|
|
|
|
>
|
|
|
> Starting with `base-4.9.0.0`, `Data.Semigroup` has moved into `base`, kicking off the [prime:Libraries/Proposals/SemigroupMonoid](https://prime.haskell.org/intertrac/Libraries/Proposals/SemigroupMonoid) roadmap which will eventually lead to have `Semigroup` become a proper superclass of `Monoid`.
|
|
|
Starting with `base-4.9.0.0`, `Data.Semigroup` has moved into `base`, kicking off the [prime:Libraries/Proposals/SemigroupMonoid](https://prime.haskell.org/intertrac/Libraries/Proposals/SemigroupMonoid) roadmap which will eventually lead to have `Semigroup` become a proper superclass of `Monoid`.
|
|
|
|
|
|
>
|
|
|
> In order to smooth the transition, it's important to have `Semigroup` instances in place as soon as possible, especially in library packages. In order to aid detecting missing instances two warnings have been implemented in GHC 8.0 (both implied by `-Wcompat`): `-Wnoncanonical-monoid-instances` and `-Wsemigroup`. Those warnings also help defining the instances in compliance with the envisioned transition scheme.
|
|
|
In order to smooth the transition, it's important to have `Semigroup` instances in place as soon as possible, especially in library packages. In order to aid detecting missing instances two warnings have been implemented in GHC 8.0 (both implied by `-Wcompat`): `-Wnoncanonical-monoid-instances` and `-Wsemigroup`. Those warnings also help defining the instances in compliance with the envisioned transition scheme.
|
|
|
|
|
|
>
|
|
|
> The [hackage:semigroups](http://hackage.haskell.org/package/semigroups) package can be used to avoid `-XCPP` usage by providing the same `Data.Semigroup` module for older GHCs.
|
|
|
The [hackage:semigroups](http://hackage.haskell.org/package/semigroups) package can be used to avoid `-XCPP` usage by providing the same `Data.Semigroup` module for older GHCs.
|
|
|
|
|
|
<table><tr><th>Provide `MonadFail` instances</th>
|
|
|
<td></td></tr></table>
|
|
|
|
|
|
>
|
|
|
> See [prime:Libraries/Proposals/MonadFail](https://prime.haskell.org/intertrac/Libraries/Proposals/MonadFail) for more details.
|
|
|
See [prime:Libraries/Proposals/MonadFail](https://prime.haskell.org/intertrac/Libraries/Proposals/MonadFail) for more details.
|
|
|
|
|
|
>
|
|
|
> Again, in order to extend the compatibility window of your code it's recommended to provide instances early on. To this end, two warnings have been implemented to help with detecting code needing attention: `-Wmissing-monadfail-instances` (implied by `-Wcompat`) and `-Wnoncanonical-monadfail-instances` (not implied by `-Wcompat`).
|
|
|
Again, in order to extend the compatibility window of your code it's recommended to provide instances early on. To this end, two warnings have been implemented to help with detecting code needing attention: `-Wmissing-monadfail-instances` (implied by `-Wcompat`) and `-Wnoncanonical-monadfail-instances` (not implied by `-Wcompat`).
|
|
|
|
|
|
>
|
|
|
> The [hackage:fail](http://hackage.haskell.org/package/fail) package helps avoiding `-XCPP` usage and emulates the new `Control.Monad.Fail` module.
|
|
|
The [hackage:fail](http://hackage.haskell.org/package/fail) package helps avoiding `-XCPP` usage and emulates the new `Control.Monad.Fail` module.
|
|
|
|
|
|
#### Reworked `HasCallStack` API
|
|
|
|
|
|
|
|
|
GHC's callstack interface (formerly known as "implicit call stacks") is been reworked, hiding the implicit parameter behind a constraint synonym,
|
|
|
|
|
|
```
|
|
|
typeHasCallStack=(?callStack ::CallStack)::Constraint
|
|
|
```hs
|
|
|
type HasCallStack = (?callStack :: CallStack) :: Constraint
|
|
|
```
|
|
|
|
|
|
|
... | ... | @@ -181,21 +191,26 @@ Existing users of this functionality taking `callStack` arguments should be refa |
|
|
|
|
|
For instance,
|
|
|
|
|
|
```
|
|
|
{-# LANGUAGE ImplicitParams #-}moduleAssertOddwhereimportGHC.Stack(CallStack)assertOdd::(?callStack ::CallStack)=>Int-> a -> a
|
|
|
```hs
|
|
|
{-# LANGUAGE ImplicitParams #-}
|
|
|
module AssertOdd where
|
|
|
import GHC.Stack (CallStack)
|
|
|
assertOdd :: (?callStack :: CallStack) => Int -> a -> a
|
|
|
assertOdd n
|
|
|
| odd n = id
|
|
|
| otherwise =error"That number isn't odd!"
|
|
|
| otherwise = error "That number isn't odd!"
|
|
|
```
|
|
|
|
|
|
|
|
|
turns in to,
|
|
|
|
|
|
```
|
|
|
moduleAssertOddwhereimportGHC.Stack(HasCallStack)assertOdd::HasCallStack=>Int-> a -> a
|
|
|
```hs
|
|
|
module AssertOdd where
|
|
|
import GHC.Stack (HasCallStack)
|
|
|
assertOdd :: HasCallStack => Int -> a -> a
|
|
|
assertOdd n
|
|
|
| odd n = id
|
|
|
| otherwise =error"That number isn't odd!"
|
|
|
| otherwise = error "That number isn't odd!"
|
|
|
```
|
|
|
|
|
|
#### New `Generic` metadata representation
|
... | ... | @@ -203,36 +218,61 @@ assertOdd n |
|
|
|
|
|
GHC 8.0 changes the way GHC generics encodes metadata. Previously, an empty data type would be generated for every datatype, constructor, and record selector associated with a `Generic` instance. For example:
|
|
|
|
|
|
```
|
|
|
dataExample a =Example a derivingGeneric
|
|
|
```hs
|
|
|
data Example a = Example a deriving Generic
|
|
|
```
|
|
|
|
|
|
|
|
|
would have generated the following code prior to GHC 8.0:
|
|
|
|
|
|
```
|
|
|
instanceGeneric(Example a)wheretypeRep(Example a)=D1D1Example(C1C1_0Example(S1NoSelector(Rec0 a)))...dataD1ExampledataC1_0ExampleinstanceDatatypeD1Examplewhere...instanceConstructorC1_0Examplewhere...
|
|
|
```hs
|
|
|
instance Generic (Example a) where
|
|
|
type Rep (Example a) =
|
|
|
D1 D1Example
|
|
|
(C1 C1_0Example
|
|
|
(S1 NoSelector (Rec0 a)))
|
|
|
...
|
|
|
|
|
|
data D1Example
|
|
|
data C1_0Example
|
|
|
|
|
|
instance Datatype D1Example where ...
|
|
|
instance Constructor C1_0Example where ...
|
|
|
```
|
|
|
|
|
|
|
|
|
GHC 8.0, on the other hand, does not generate empty data types. The `M1` data type in `GHC.Generics` has been modified so that it is parameterized by a new `Meta` type:
|
|
|
|
|
|
```
|
|
|
dataMeta=MetaDataSymbolSymbolSymbolBool|MetaConsSymbolFixityIBool|MetaSel(MaybeSymbol)SourceUnpackednessSourceStrictnessDecidedStrictnessnewtypeM1(i ::*)(c ::Meta)(f ::*->*)(p ::*)=M1{ unM1 :: f p }typeD1=M1DtypeC1=M1CtypeS1=M1S
|
|
|
```hs
|
|
|
data Meta = MetaData Symbol Symbol Symbol Bool
|
|
|
| MetaCons Symbol FixityI Bool
|
|
|
| MetaSel (Maybe Symbol) SourceUnpackedness SourceStrictness DecidedStrictness
|
|
|
|
|
|
newtype M1 (i :: *) (c :: Meta) (f :: * -> *) (p :: *) = M1 { unM1 :: f p }
|
|
|
type D1 = M1 D
|
|
|
type C1 = M1 C
|
|
|
type S1 = M1 S
|
|
|
```
|
|
|
|
|
|
|
|
|
There is now only one instance for `Datatype`, `Constructor`, and `Selector`. (For more information on how this works, see [this](https://gitlab.haskell.org/trac/ghc/wiki/Commentary/Compiler/GenericDeriving#Type-levelmetadataencoding).)
|
|
|
|
|
|
```
|
|
|
instanceDatatype('MetaData n m p nt)where...instanceConstructor('MetaCons n f r)where...instanceSelector('MetaSel mn su ss ds)where...
|
|
|
```hs
|
|
|
instance Datatype ('MetaData n m p nt) where ...
|
|
|
instance Constructor ('MetaCons n f r) where ...
|
|
|
instance Selector ('MetaSel mn su ss ds) where ...
|
|
|
```
|
|
|
|
|
|
|
|
|
One major consequence of the additions to `MetaSel` is that the `NoSelector` datatype is insufficient to express all of the strictness properties of a record selector, so `NoSelector` was removed. If your generics-related code only mentions the `Datatype`, `Constructor`, and `Selector` typeclasses, it will not need to change. If your code does something more ambitious like checking for the presence of `NoSelector`, it will need to be updated to use `MetaSel` instead. For example, the above `Example` would have the following code generated:
|
|
|
|
|
|
```
|
|
|
instanceGeneric(Example a)wheretypeRep(Example a)=D1('MetaData"Example""Module""package"'False)(C1('MetaCons"Example"'PrefixI'False)(S1('MetaSel'Nothing'NoSourceUnpackedness'NoSourceStrictness'DecidedLazy)(Rec0 a)))
|
|
|
```hs
|
|
|
instance Generic (Example a) where
|
|
|
type Rep (Example a) =
|
|
|
D1 ('MetaData "Example" "Module" "package" 'False)
|
|
|
(C1 ('MetaCons "Example" 'PrefixI 'False)
|
|
|
(S1 ('MetaSel 'Nothing 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy)
|
|
|
(Rec0 a)))
|
|
|
```
|
|
|
|
|
|
|
... | ... | @@ -244,51 +284,62 @@ Notice that since `Example` has no record selector, it generated `('MetaSel 'Not |
|
|
|
|
|
- the `DataD`, `NewtypeD`, `DataInstD`, and `NewtypeInstD` constructors have a new field `Maybe Kind` ([\#10828](https://gitlab.haskell.org//ghc/ghc/issues/10828)), and take a `CxtQ` instead of a `[Name]` for the derived classes ([\#10819](https://gitlab.haskell.org//ghc/ghc/issues/10819)). If you don't know what to do, use `Nothing` for the kind signature. The field that used to be of type `[Name]` can be converted to a `CxtQ` using `mapM conT`.
|
|
|
|
|
|
```wiki
|
|
|
- dataD :: CxtQ -> Name -> [TyVarBndr] -> [ConQ] -> [Name] -> DecQ
|
|
|
+ dataD :: CxtQ -> Name -> [TyVarBndr] -> Maybe Kind -> [ConQ] -> CxtQ -> DecQ
|
|
|
```diff
|
|
|
- dataD :: CxtQ -> Name -> [TyVarBndr] -> [ConQ] -> [Name] -> DecQ
|
|
|
+ dataD :: CxtQ -> Name -> [TyVarBndr] -> Maybe Kind -> [ConQ] -> CxtQ -> DecQ
|
|
|
|
|
|
- newtypeD :: CxtQ -> Name -> [TyVarBndr] -> ConQ -> [Name] -> DecQ
|
|
|
+ newtypeD :: CxtQ -> Name -> [TyVarBndr] -> Maybe Kind -> ConQ -> CxtQ -> DecQ
|
|
|
- newtypeD :: CxtQ -> Name -> [TyVarBndr] -> ConQ -> [Name] -> DecQ
|
|
|
+ newtypeD :: CxtQ -> Name -> [TyVarBndr] -> Maybe Kind -> ConQ -> CxtQ -> DecQ
|
|
|
|
|
|
- dataInstD :: CxtQ -> Name -> [TypeQ] -> [ConQ] -> [Name] -> DecQ
|
|
|
+ dataInstD :: CxtQ -> Name -> [TypeQ] -> Maybe Kind -> [ConQ] -> CxtQ -> DecQ
|
|
|
- dataInstD :: CxtQ -> Name -> [TypeQ] -> [ConQ] -> [Name] -> DecQ
|
|
|
+ dataInstD :: CxtQ -> Name -> [TypeQ] -> Maybe Kind -> [ConQ] -> CxtQ -> DecQ
|
|
|
|
|
|
- newtypeInstD :: CxtQ -> Name -> [TypeQ] -> ConQ -> [Name] -> DecQ
|
|
|
+ newtypeInstD :: CxtQ -> Name -> [TypeQ] -> Maybe Kind -> ConQ -> CxtQ -> DecQ
|
|
|
- newtypeInstD :: CxtQ -> Name -> [TypeQ] -> ConQ -> [Name] -> DecQ
|
|
|
+ newtypeInstD :: CxtQ -> Name -> [TypeQ] -> Maybe Kind -> ConQ -> CxtQ -> DecQ
|
|
|
```
|
|
|
|
|
|
- The `Strict` datatype has been overhauled. The functional equivalent of `Strict` in `template-haskell-2.11.0.0` is `Bang`:
|
|
|
|
|
|
```
|
|
|
dataBang=BangSourceUnpackednessSourceStrictnessdataSourceUnpackedness=NoSourceUnpackedness-- ^ @C a@|SourceNoUnpack-- ^ @C {-# NOUNPACK #-} a@|SourceUnpack-- ^ @C {-# UNPACK #-} a@dataSourceStrictness=NoSourceStrictness-- ^ @C a@|SourceLazy-- ^ @C ~a@|SourceStrict-- ^ @C !a@typeBangType=(Bang,Type)typeVarBangType=(Name,Bang,Type)
|
|
|
```hs
|
|
|
data Bang = Bang SourceUnpackedness SourceStrictness
|
|
|
|
|
|
data SourceUnpackedness
|
|
|
= NoSourceUnpackedness -- ^ @C a@
|
|
|
| SourceNoUnpack -- ^ @C {-# NOUNPACK #-} a@
|
|
|
| SourceUnpack -- ^ @C {-# UNPACK #-} a@
|
|
|
|
|
|
data SourceStrictness = NoSourceStrictness -- ^ @C a@
|
|
|
| SourceLazy -- ^ @C ~a@
|
|
|
| SourceStrict -- ^ @C !a@
|
|
|
|
|
|
type BangType = (Bang, Type)
|
|
|
type VarBangType = (Name, Bang, Type)
|
|
|
```
|
|
|
|
|
|
Note that the notions of unpackedness and strictness, which were previously combined in `Strict`, have now been decoupled. Also note the emphasis on *source*, as `Bang` represents what the user writes in source code. A field's *source* strictness may be quite different from what GHC actually *decides* to use as a field's strictness.
|
|
|
|
|
|
>
|
|
|
> For example, if `-XStrict` is enabled, GHC will decided that any field not marked with a laziness annotation (`~`) will become strict. So if you compile the following datatype with `-XStrict` enabled:
|
|
|
>
|
|
|
> ```
|
|
|
> dataExample a =Example a
|
|
|
> ```
|
|
|
>
|
|
|
>
|
|
|
> GHC will decide that `Example`'s field is strict. However, if you reify `Example`, its `Bang` value will be `Bang NoSourceUnpackedness NoSourceStrictness` because the user did not put an explicit strictness annotation (`!`) in the source code. To figure out what GHC decided, use the `reifyConStrictness` function:
|
|
|
>
|
|
|
> ```
|
|
|
> reifyConStrictness::Name->Q[DecidedStrictness]dataDecidedStrictness=DecidedLazy|DecidedStrict|DecidedUnpack
|
|
|
> ```
|
|
|
For example, if `-XStrict` is enabled, GHC will decided that any field not marked with a laziness annotation (`~`) will become strict. So if you compile the following datatype with `-XStrict` enabled:
|
|
|
|
|
|
- The `InstanceD` constructor
|
|
|
```hs
|
|
|
data Example a = Example a
|
|
|
```
|
|
|
|
|
|
GHC will decide that `Example`'s field is strict. However, if you reify `Example`, its `Bang` value will be `Bang NoSourceUnpackedness NoSourceStrictness` because the user did not put an explicit strictness annotation (`!`) in the source code. To figure out what GHC decided, use the `reifyConStrictness` function:
|
|
|
|
|
|
This was a late change introduced in GHC 8.0 RC4, see [discussion](https://mail.haskell.org/pipermail/ghc-devs/2016-April/011803.html) for more details.
|
|
|
```hs
|
|
|
reifyConStrictness :: Name -> Q [DecidedStrictness]
|
|
|
|
|
|
data DecidedStrictness = DecidedLazy
|
|
|
| DecidedStrict
|
|
|
| DecidedUnpack
|
|
|
```
|
|
|
|
|
|
of type `Dec` has an additional field of type `Maybe Overlap`. It is used to specify the overlapping behavior for the instances, as with the `{-# OVERLAP/S/PED/PING #-}` pragmas:
|
|
|
- The `InstanceD` constructor of type `Dec` has an additional field of type `Maybe Overlap`. It is used to specify the overlapping behavior for the instances, as with the `{-# OVERLAP/S/PED/PING #-}` pragmas:
|
|
|
|
|
|
```
|
|
|
dataDec=...|InstanceD(MaybeOverlap)CxtType[Dec]|...dataOverlap=Overlappable|Overlapping|Overlaps|Incoherent
|
|
|
```hs
|
|
|
data Dec = ... | InstanceD (Maybe Overlap) Cxt Type [Dec] | ...
|
|
|
|
|
|
data Overlap = Overlappable | Overlapping | Overlaps | Incoherent
|
|
|
```
|
|
|
|
|
|
Note that to reduce code breakage, and to support the common case, the corresponding `instanceD` function was not changed---it will produce instances where the "overlap" field is set to `Nothing`. To generate instances with a specific overlapping behavior, please use `instanceWithOverlapD`.
|
... | ... | @@ -302,14 +353,14 @@ Notice that since `Example` has no record selector, it generated `('MetaSel 'Not |
|
|
|
|
|
Starting with version 0.68 [hackage:hsc2hs](http://hackage.haskell.org/package/hsc2hs) now supports the `#alignment` macro, which can be used to calculate the alignment of a struct in bytes. It is common for `.hsc` files to implement `#alignment` manually via a `#let` directive:
|
|
|
|
|
|
```
|
|
|
#let alignment t ="%lu",(unsigned long)offsetof(struct {char x__; t (y__);}, y__)
|
|
|
```hs
|
|
|
#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)
|
|
|
```
|
|
|
|
|
|
|
|
|
This command was incorporated into `hsc2hs` with the release of GHC 8.0. As a result, if you have the above directive in your code, it will now emit a warning when compiled with GHC 8.0:
|
|
|
|
|
|
```wiki
|
|
|
```
|
|
|
Module.hsc:24:0: warning: "hsc_alignment" redefined [enabled by default]
|
|
|
In file included from dist/build/Module_hsc_make.c:1:0:
|
|
|
/path/to/ghc/lib/template-hsc.h:88:0: note: this is the location of the previous definition
|
... | ... | @@ -320,8 +371,10 @@ In file included from dist/build/Module_hsc_make.c:1:0: |
|
|
|
|
|
To make your code free of warnings on GHC 8.0 and earlier versions, surround the directive with a pragma checking for the right GHC version:
|
|
|
|
|
|
```
|
|
|
#if __GLASGOW_HASKELL__ <800#let alignment t ="%lu",(unsigned long)offsetof(struct {char x__; t (y__);}, y__)#endif
|
|
|
```hs
|
|
|
#if __GLASGOW_HASKELL__ < 800
|
|
|
#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)
|
|
|
#endif
|
|
|
```
|
|
|
|
|
|
---
|
... | ... | |