Generic1 deriving should use more coercions
Consider
```hs
newtype Foo a = Foo (Maybe [a]) deriving (Generic1)
```
This produces some rather unsatisfactory Core:
```
-- to1 worker
Travv.$fGeneric1Foo1 :: forall a. Rep1 Foo a -> Maybe [a]
Travv.$fGeneric1Foo1
= \ (@ a_a7RL) (ds_d9dZ :: Rep1 Foo a_a7RL) ->
case ds_d9dZ `cast` <Co:103> of {
Nothing -> GHC.Maybe.Nothing @ [a_a7RL];
Just a1_a9fD -> GHC.Maybe.Just @ [a_a7RL] (a1_a9fD `cast` <Co:5>)
}
-- from1 worker
Travv.$fGeneric1Foo2 :: forall a. Foo a -> Maybe (Rec1 [] a)
Travv.$fGeneric1Foo2
= \ (@ a_a7R6) (x_a7GJ :: Foo a_a7R6) ->
case x_a7GJ `cast` <Co:2> of {
Nothing -> GHC.Maybe.Nothing @ (Rec1 [] a_a7R6);
Just a1_a9fD ->
GHC.Maybe.Just @ (Rec1 [] a_a7R6) (a1_a9fD `cast` <Co:6>)
}
```
Both of these functions could be implemented as safe coercions, but neither of them is! Similarly, if I define
```hs
data Bar a = Bar (Maybe [a]) deriving Generic1
```
I get a `to1` worker that looks like
```
Travv.$fGeneric1Bar_$cto1 :: forall a. Rep1 Bar a -> Bar a
Travv.$fGeneric1Bar_$cto1
= \ (@ a_a7UA) (ds_d9ho :: Rep1 Bar a_a7UA) ->
Travv.Bar
@ a_a7UA
(case ds_d9ho `cast` <Co:103> of {
Nothing -> GHC.Maybe.Nothing @ [a_a7UA];
Just a1_a9iK -> GHC.Maybe.Just @ [a_a7UA] (a1_a9iK `cast` <Co:5>)
})
```
That `case` expression should really just be a cast.
I think the basic trick is probably to inspect the role of the type argument of each type in a composition, using that to work out whether to coerce that step.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.6.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | RyanGlScott |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Generic1 deriving should use more coercions","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.8.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.6.2","keywords":["Generics"],"differentials":[],"test_case":"","architecture":"","cc":["RyanGlScott"],"type":"Bug","description":"Consider\r\n\r\n{{{#!hs\r\nnewtype Foo a = Foo (Maybe [a]) deriving (Generic1)\r\n}}}\r\n\r\nThis produces some rather unsatisfactory Core:\r\n\r\n{{{\r\n-- to1 worker\r\nTravv.$fGeneric1Foo1 :: forall a. Rep1 Foo a -> Maybe [a]\r\nTravv.$fGeneric1Foo1\r\n = \\ (@ a_a7RL) (ds_d9dZ :: Rep1 Foo a_a7RL) ->\r\n case ds_d9dZ `cast` <Co:103> of {\r\n Nothing -> GHC.Maybe.Nothing @ [a_a7RL];\r\n Just a1_a9fD -> GHC.Maybe.Just @ [a_a7RL] (a1_a9fD `cast` <Co:5>)\r\n}\r\n\r\n-- from1 worker\r\nTravv.$fGeneric1Foo2 :: forall a. Foo a -> Maybe (Rec1 [] a)\r\nTravv.$fGeneric1Foo2\r\n = \\ (@ a_a7R6) (x_a7GJ :: Foo a_a7R6) ->\r\n case x_a7GJ `cast` <Co:2> of {\r\n Nothing -> GHC.Maybe.Nothing @ (Rec1 [] a_a7R6);\r\n Just a1_a9fD ->\r\n GHC.Maybe.Just @ (Rec1 [] a_a7R6) (a1_a9fD `cast` <Co:6>)\r\n }\r\n}}}\r\n\r\nBoth of these functions could be implemented as safe coercions, but neither of them is! Similarly, if I define\r\n\r\n{{{#!hs\r\ndata Bar a = Bar (Maybe [a]) deriving Generic1\r\n}}}\r\n\r\nI get a `to1` worker that looks like\r\n\r\n{{{\r\nTravv.$fGeneric1Bar_$cto1 :: forall a. Rep1 Bar a -> Bar a\r\nTravv.$fGeneric1Bar_$cto1\r\n = \\ (@ a_a7UA) (ds_d9ho :: Rep1 Bar a_a7UA) ->\r\n Travv.Bar\r\n @ a_a7UA\r\n (case ds_d9ho `cast` <Co:103> of {\r\n Nothing -> GHC.Maybe.Nothing @ [a_a7UA];\r\n Just a1_a9iK -> GHC.Maybe.Just @ [a_a7UA] (a1_a9iK `cast` <Co:5>)\r\n })\r\n}}}\r\n\r\nThat `case` expression should really just be a cast.\r\n\r\nI think the basic trick is probably to inspect the role of the type argument of each type in a composition, using that to work out whether to coerce that step.","type_of_failure":"OtherFailure","blocking":[]} -->
issue