Skip to content
GitLab
Projects Groups Topics Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Register
  • Sign in
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
    • Locked files
  • Issues 5.5k
    • Issues 5.5k
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 631
    • Merge requests 631
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Artifacts
    • Schedules
    • Test cases
  • Deployments
    • Deployments
    • Releases
  • Packages and registries
    • Packages and registries
    • Model experiments
  • Analytics
    • Analytics
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Glasgow Haskell CompilerGlasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #15969

Generic1 deriving should use more coercions

Consider

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

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.

Trac metadata
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
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking