Skip to content

the syntax highlighting of a field name used as a function and a field used with -XOverloadedRecordDot should look the same #4501

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
MangoIV opened this issue Feb 17, 2025 · 3 comments
Labels
component: semantic-tokens type: bug Something isn't right: doesn't work as intended, documentation is missing/outdated, etc.. type: enhancement New feature or request

Comments

@MangoIV
Copy link
Contributor

MangoIV commented Feb 17, 2025

Is your enhancement request related to a problem? Please describe.

  • for some reason, fields when used as functions get highlighted as fields, but when used as accessors using overloaded record dot, get highlighted as functions

Describe the solution you'd like

  • both get highlighted as record accessors (distinct from function highlighting)

Describe alternatives you've considered

n/a

Additional context

  • I'm using semantic highlighting
@soulomoon
Copy link
Collaborator

Should be related to how hie present the node. I'll take a look.

@soulomoon soulomoon added component: semantic-tokens type: bug Something isn't right: doesn't work as intended, documentation is missing/outdated, etc.. and removed status: needs triage labels Feb 17, 2025
@soulomoon
Copy link
Collaborator

soulomoon commented Feb 17, 2025

For

{-# LANGUAGE OverloadedRecordDot #-}

module Hello where

data Foo = Foo { foo :: Int }

myFoo = Foo { foo = 1 }

main :: IO ()
main = do
    let x = myFoo.foo
    print x

The related HieAst node does not show information about .foo.

              [email protected]:11:9: Source: From source
                                  {(annotations: {}),  (types: []), 
                                   (identifier info: {(name x,  Details:  Just 0 {LHS of a match group,
                                                                                  regular value bound with scope: LocalScope hello.hs:(11,9)-(12,11) bound at: hello.hs:11:9-21})})}
                                  
              [email protected]:11:11-21: Source: From source
                                      {(annotations: {(GRHS, GRHS)}),  (types: []), 
                                       (identifier info: {})}
                                      
                [email protected]:11:13-21: Source: From source
                                        {(annotations: {(HsApp, HsExpr), (XExpr, HsExpr)}), 
                                         (types: [0]),  (identifier info: {})}
                                        
                  [email protected]:11:13-17: Source: From source
                                          {(annotations: {(HsVar, HsExpr)}),  (types: [2]), 
                                           (identifier info: {(name myFoo,  Details:  Just 2 {usage})})}

But for typechecked source, the FieldLabelString is there. likely it does not convert to the node in hieast

                                                (XExpr
                                                 (ExpandedThingTc
                                                  (OrigExpr
                                                   (HsGetField
                                                    (NoExtField)
                                                    (L
                                                     (EpAnn
                                                      (EpaSpan { hello.hs:11:13-17 })
                                                      (AnnListItem
                                                       [])
                                                      (EpaComments
                                                       []))
                                                     (HsVar
                                                      (NoExtField)
                                                      (L
                                                       (EpAnn
                                                        (EpaSpan { hello.hs:11:13-17 })
                                                        (NameAnnTrailing
                                                         [])
                                                        (EpaComments
                                                         []))
                                                       {Name: myFoo})))
                                                    (L
                                                     (EpAnn
                                                      (EpaSpan { hello.hs:11:18-21 })
                                                      (NoEpAnns)
                                                      (EpaComments
                                                       []))
                                                     (DotFieldOcc
                                                      (AnnFieldLabel
                                                       (Just
                                                        (EpaSpan { hello.hs:11:18 })))
                                                      (L
                                                       (EpAnn
                                                        (EpaSpan { hello.hs:11:19-21 })
                                                        (NameAnnTrailing
                                                         [])
                                                        (EpaComments
                                                         []))
                                                       (FieldLabelString
                                                        {FastString: "foo"}))))))

@soulomoon
Copy link
Collaborator

soulomoon commented Feb 17, 2025

To fix this, we need to modify the hieast generation in ghc. More specifically at ghc source code.
We can see the OrigExpr is omited all togather.
I would be helpful to see Note [Overview of record dot syntax]

================ update ===========

After looking into the ghc code, I think it might not be easy. The main problem is the ".foo" remains to be just FieldLabelString in the artifact ghc generated and does not resolve to the actual field Name.

For overloadedDot, ghc make a serious of trasformation from the source code through HasField type class,
And the field existency checking occur in the solver during typechecking through matchGlobalInst.
But it does not add (a reference to the actual field) in typecheckedSource nor renamedSource for us to relate the FieldLabelString back to the actual field Name.

Possible solutions:

  1. update the GHC TTG with this additional bit of information, maybe add it back when renaming.
  2. A possible easier ad-hoc workaround after the landing of new entity map in the HieFile,
    That is to assign a new name in the generation of HieAst and add it as a field Entity in the entity map just for the sake of semantic highlighting. But we would still be lacking the type information and jump over feature a like for this symbol.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: semantic-tokens type: bug Something isn't right: doesn't work as intended, documentation is missing/outdated, etc.. type: enhancement New feature or request
Projects
None yet
2 participants