The credit goes to wuzzeb for originally discovering this bug here. I've minimized their test case slightly below:
{-# LANGUAGE StrictData #-}{-# LANGUAGE TypeFamilies #-}moduleBugwheredatafamilyTnewtypeinstanceT=MkTIntderivingEq
With optimization enabled, this program compiles with GHC 8.0.2 through 8.4.4, but not with 8.6.3 or HEAD:
$ /opt/ghc/8.4.4/bin/ghc -fforce-recomp -O Bug.hs[1 of 1] Compiling Bug ( Bug.hs, Bug.o )$ /opt/ghc/8.6.3/bin/ghc -fforce-recomp -O Bug.hs[1 of 1] Compiling Bug ( Bug.hs, Bug.o )Bug.hs:6:39: error: • Couldn't match a lifted type with an unlifted type arising from the coercion of the method ‘==’ from type ‘GHC.Prim.Int# -> GHC.Prim.Int# -> Bool’ to type ‘T -> T -> Bool’ • When deriving the instance for (Eq T) |6 | newtype instance T = MkT Int deriving Eq | ^^
Based on the error message, it appears as if GHC mistakenly believes that the representation type of the T instance is Int#, rather than Int.
Trac metadata
Trac field
Value
Version
8.6.3
Type
Bug
TypeOfFailure
OtherFailure
Priority
highest
Resolution
Unresolved
Component
Compiler (Type checker)
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Child items
0
Show closed items
No child items are currently assigned. Use child items to break down this issue into smaller parts.
I'm starting to think that this is actually an old bug with StrictData, since the following program (which uses a plain old newtype, not a data family) also breaks Core Lint in a similar fashion with GHC 8.4.4 or later:
{-# LANGUAGE GADTs #-}{-# LANGUAGE ScopedTypeVariables #-}{-# LANGUAGE StrictData #-}moduleBugwherenewtypeTabwhereMkT::forallba.Int->Tab
$ /opt/ghc/8.4.4/bin/ghc -O -dcore-lint Bug.hs [1 of 1] Compiling Bug ( Bug.hs, Bug.o )*** Core Lint errors : in result of Tidy Core ***<no location info>: warning: In a case alternative: (I# dt_aXx :: Int#) Type of case alternatives not the same as the annotation on case: Actual type: T a_atk b_atj Annotation on case: T b_atj a_atk Alt Rhs: dt_aXx `cast` (Sym (N:T[0] <a_atk>_P <b_atj>_P) :: (Int# :: TYPE 'IntRep) ~R# (T a_atk b_atj :: *))*** Offending Program ***$WMkT [InlPrag=INLINE[2]] :: forall b a. Int -> T a b[GblId[DataConWrapper], Arity=1, Caf=NoCafRefs, Str=<S,U>, Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=False) Tmpl= \ (@ b_atj) (@ a_atk) (dt_aXw [Occ=Once!] :: Int) -> case dt_aXw of { I# dt_aXx [Occ=Once] -> dt_aXx `cast` (Sym (N:T[0] <a_atk>_P <b_atj>_P) :: (Int# :: TYPE 'IntRep) ~R# (T a_atk b_atj :: *)) }}]$WMkT = \ (@ b_atj) (@ a_atk) (dt_aXw [Occ=Once!] :: Int) -> case dt_aXw of { I# dt_aXx [Occ=Once] -> dt_aXx `cast` (Sym (N:T[0] <a_atk>_P <b_atj>_P) :: (Int# :: TYPE 'IntRep) ~R# (T a_atk b_atj :: *)) }<elided>
The issue appears to involve newtypes with wrappers in general. (The reason why the original program only started breaking with GHC 8.6 is because commit eb680f2c changed GHC's treatment of newtype instances so that they would have wrappers where they didn't before.)
The mention of Int# has me wondering: is GHC trying to unpack the Int field of MkT? If so, I would surely think that that's incorrect, since the idea of unpacking a newtype seems bogus, especially since GHC rejects this program:
λ> newtype T = MkT {-# UNPACK #-} !Int<interactive>:1:13: error: • A newtype constructor cannot have a strictness annotation, but ‘MkT’ does • In the definition of data constructor ‘MkT’ In the newtype declaration for ‘T’
Perhaps the implementation of StrictData misses this fact, however. I'll check the code to see if that is the case.
My hunch appears to be correct. The dataConSrcToImplBang function is what is responsible for making decisions about strictness/unpacking w.r.t. StrictData:
-- | Unpack/Strictness decisions from source moduledataConSrcToImplBang::DynFlags->FamInstEnvs->Type->HsSrcBang->HsImplBangdataConSrcToImplBangdflagsfam_envsarg_ty(HsSrcBangannunpkNoSrcStrict)|xoptLangExt.StrictDatadflags-- StrictData => strict field=dataConSrcToImplBangdflagsfam_envsarg_ty(HsSrcBangannunpkSrcStrict)|otherwise-- no StrictData => lazy field=HsLazy
Notice that this does not take into account whether the Type of the field belongs to a newtype or not, so this will indeed unpack the field of a newtype with StrictData + -O enabled. Yikes.
One could fix this by propagating information about whether we're in a newtype or not to dataConSrcToImplBang. But then again, should we really even need to call dataConSrcToImplBang if we're dealing with a newtype? dataConSrcToImplBang is internal to MkId and only has one call site, so I'm inclined to just avoid invoking it at its call site, like so:
diff --git a/compiler/basicTypes/MkId.hs b/compiler/basicTypes/MkId.hsindex 5a6f1fbf96..fa3d6785b7 100644--- a/compiler/basicTypes/MkId.hs+++ b/compiler/basicTypes/MkId.hs@@ -637,11 +637,15 @@ mkDataConRep dflags fam_envs wrap_name mb_bangs data_con -- Because we are going to apply the eq_spec args manually in the -- wrapper- arg_ibangs =- case mb_bangs of- Nothing -> zipWith (dataConSrcToImplBang dflags fam_envs)- orig_arg_tys orig_bangs- Just bangs -> bangs+ new_tycon = isNewTyCon tycon+ arg_ibangs+ | new_tycon+ = nOfThem (length orig_arg_tys) HsLazy+ | otherwise+ = case mb_bangs of+ Nothing -> zipWith (dataConSrcToImplBang dflags fam_envs)+ orig_arg_tys orig_bangs+ Just bangs -> bangs (rep_tys_w_strs, wrappers) = unzip (zipWith dataConArgRep all_arg_tys (ev_ibangs ++ arg_ibangs))@@ -650,7 +654,7 @@ mkDataConRep dflags fam_envs wrap_name mb_bangs data_con (rep_tys, rep_strs) = unzip (concat rep_tys_w_strs) wrapper_reqd =- (not (isNewTyCon tycon)+ (not new_tycon -- (Most) newtypes have only a worker, with the exception -- of some newtypes written with GADT syntax. See below. && (any isBanged (ev_ibangs ++ arg_ibangs)
This certainly fixes the two programs in this ticket, and it passes the rest of the testsuite. Does this sound like the right approach?
commit 076f5862a9e46eef762ba19fb7b14e75fa03c2c0Author: Ryan Scott <ryan.gl.scott@gmail.com>Date: Sat Jan 12 19:05:46 2019 -0500 Don't invoke dataConSrcToImplBang on newtypes
Given the severity of this bug, and that fact that there have been multiple bug reports about this (see #16191 (closed) for another one), I'll optimistically mark this as a candidate for merging into the upcoming 8.6.4 release.