Skip to content

GitLab

  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,866
    • Issues 4,866
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 455
    • Merge requests 455
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Releases
  • Analytics
    • Analytics
    • Value stream
    • 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 Compiler
  • GHCGHC
  • Issues
  • #17381
Closed
Open
Created Oct 20, 2019 by mniip@mniipReporter

DuplicateRecordFields and quasiquoters

GHC seems to parse record constructions/updates differently when DuplicateRecordFields is in effect, and that seems to reflect in the data returned from expression quasiquotes:

data D = D { fld :: () }                                                        
                                                                                
[|D { fld = () }|]
-- without DuplicateRecordFields:
-- RecConE Main.D [(Main.fld, ConE GHC.Tuple.())]
-- with DuplicateRecordFields:
-- RecConE Main.D [(Main.$sel:fld:D, ConE GHC.Tuple.())]

                                                              
[|d { fld = () }|]
-- without DuplicateRecordFields:
-- RecUpdE (UnboundVarE d) [(Main.fld, ConE GHC.Tuple.())]
-- with DuplicateRecordFields:
-- RecUpdE (UnboundVarE d) [(Main.$sel:fld:D, ConE GHC.Tuple.())]

Of interest is the selector Main.$sel:fld:D. It has a name characteristic of GHC Core internal names. The quirkiness manifests in that we cannot lookupValueName "$sel:fld:D", and the renamer won't in general pick it up if we use Name (mkOccName "$sel:fld:D") NameS or even Name (mkOccName "$sel:fld:D") $ NameQ $ mkModName "Main". Only Name (mkOccName "$sel:fld:D") $ NameG VarName (mkPkgName "main") (mkModName "Main") will suffice (and that is the thing we receive from the expression quasiquoters above.

Another quirk is that when we try to reify that name we get back a declaration for a different identifier:

reify $ Name (mkOccName "$sel:fld:D") $ NameG VarName (mkPkgName "main") (mkModName "Main")
-- VarI Main.fld (AppT (AppT ArrowT (ConT Main.D)) (TupleT 0)) Nothing

Worth noting that if we do try to quasiquote an ambiguous update, we get a descriptive error message:

data D1 = D1 { fld :: () }
data D2 = D2 { fld :: () }

[|d { fld = () }|]
-- Ambiguous record updates not (yet) handled by Template Haskell
--    fld = ()

Question is, should TH know about such internal Core names at all and if so how should TH users tackle them.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking