map/coerce does not fire with all newtypes
Consider a slightly modified version of T2110, compiled with -O:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE RankNTypes #-}
import GHC.Exts
import Unsafe.Coerce
newtype Age a b where
Age :: forall a b. Int -> Age a b
foo :: [Int] -> [Int]
foo = map id
fooAge :: [Int] -> [Age a b]
fooAge = map Age
fooCoerce :: [Int] -> [Age a b]
fooCoerce = map coerce
fooUnsafeCoerce :: [Int] -> [Age a b]
fooUnsafeCoerce = map unsafeCoerce
same :: a -> b -> IO ()
same x y = case reallyUnsafePtrEquality# (unsafeCoerce x) y of
1# -> putStrLn "yes"
_ -> putStrLn "no"
main = do
let l = [1,2,3]
same (foo l) l
same (fooAge l) l
same (fooCoerce l) l
same (fooUnsafeCoerce l) l
This code correctly prints "yes" four times, as required by #2110 (closed). However, changing the order of type arguments in the definition of Age to:
Age :: forall b a. Int -> Age a b
causes the test to fail in one case: map Age
is no longer simplified to Age
. The reason is that this change causes the newtype Age
to have a wrapper, and the map/coerce rule is not detecting it (see Note [Getting the map/coerce RULE to work] and Note [Data con wrappers and GADT syntax])
This ticket is a prerequisite to linear types (since in linear types, all newtypes have wrappers).
Trac metadata
Trac field | Value |
---|---|
Version | 8.6.3 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |