Opened 3 years ago

Closed 2 years ago

#11832 closed feature request (fixed)

Allow reify to yield types in the current declaration group

Reported by: facundo.dominguez Owned by: facundo.dominguez
Priority: normal Milestone: 8.2.1
Component: Template Haskell Version: 7.10.3
Keywords: reify Cc: mboes, goldfire, simonmar, bgamari
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s): Phab:D2286 Phab:D2519
Wiki Page: TemplateHaskell/Reify

Description

Here is the motivation TemplateHaskell/Reify.

It would be useful to have a way to obtain types of identifiers in the current declaration group in splices. However, reify is defined to provide information about identifiers in previous declaration groups only.

It would be fine to allow reify to work in a scheme combined with addModFinalizer or similar so it is executed when the types are known.

Change History (22)

comment:1 Changed 2 years ago by thomie

Component: CompilerTemplate Haskell
Keywords: template-haskell removed

comment:2 Changed 2 years ago by thomie

Type: bugfeature request

comment:3 Changed 2 years ago by facundo.dominguez

Owner: set to facundo.dominguez

comment:4 Changed 2 years ago by facundo.dominguez

Differential Rev(s): Phab:D2286
Status: newpatch

comment:5 Changed 2 years ago by simonpj

I'm confused by the patch. I believe that the poster-child example is this:

f x = $(do { let name = 'x in 
           ; addModFinalizer (reify name >>= \info ->
                              runIO (print info))
           ; [| x |]) }

Now, the issue is that

  • the splice is run by the renamer
  • but you want the finaliser to have access to the type environment giving the type of x, which we only have a typecheck time.

Rather than mess around with IORefs, why not do this

data HsExpr  = ...
  | HsSpliced [Q ()] (HsExpr ..)
  ..

So the Spliced collects the finalisers emitted by the splice, but does not run them.

Now when the typechecker finds a HsSpliced, it does

tcExpr (Spliced fs e)
  = do { env <- getLclEnv
       ; addModFinaliser (setLclEnv env (sequence fs))
       ; tcExpr e }

That is, it just grabs the env, and emits a new finaliser that sets that env. Much nicer!


Generally, could we not combine addModFinaliser with addTopDecls into one primitive, by offering

later :: Q [Decl] -> Q ()

It takes a computation and puts it aside for "later" (just like addModFinaliser). But when it finally run, which happens at top level, it can produce some decls which are spliced in.

So we have

addModFinaliser thing = later (thing >> return [])

addTopDecls dec = later (return dec)

Nice!

comment:6 Changed 2 years ago by facundo.dominguez

That looks better if you can somehow implement the Data (Q ()) instance that the compiler will request for adding such field in the AST.

We could still use a Map to store the finalizers, instead of storing local type environments as we are doing now.

Combining addModFinaliser and addTopDecls looks fine to me.

Last edited 2 years ago by facundo.dominguez (previous) (diff)

comment:7 in reply to:  6 ; Changed 2 years ago by simonpj

That looks better if you can somehow implement the Data (Q ()) instance that the compiler will request for adding such field in the AST.

Well you can wrap it in a newtype and make a hand Data instance that will skip the field. The tail should not wag the dog.

We could still use a Map to store the finalizers, instead of storing local type environments as we are doing now.

I don't understand. Why would you need a Map. I gave a full implementation above.

comment:8 in reply to:  7 Changed 2 years ago by facundo.dominguez

I don't understand. Why would you need a Map. I gave a full implementation above.

Not needed if the dummy Data instance is good enough. This was an alternative to putting [Q ()] in the AST.

Last edited 2 years ago by facundo.dominguez (previous) (diff)

comment:9 Changed 2 years ago by simonmar

Cc: simonmar added

comment:10 Changed 2 years ago by Facundo Domínguez <facundo.dominguez@…>

In 567dbd9b/ghc:

Have addModFinalizer expose the local type environment.

Summary:
This annotates the splice point with 'HsSpliced ref e' where 'e' is the
result of the splice. 'ref' is a reference that the typechecker will fill with
the local type environment.

The finalizer then reads the ref and uses the local type environment, which
causes 'reify' to find local variables when run in the finalizer.

Test Plan: ./validate

Reviewers: simonpj, simonmar, bgamari, austin, goldfire

Reviewed By: goldfire

Subscribers: simonmar, thomie, mboes

Differential Revision: https://phabricator.haskell.org/D2286

GHC Trac Issues: #11832

comment:11 Changed 2 years ago by facundo.dominguez

Resolution: fixed
Status: patchclosed

comment:12 Changed 2 years ago by goldfire

Could you add a Release Note about this, as well? See docs/users_guide/8.2.1-notes.rst.

Thanks!

comment:13 Changed 2 years ago by bgamari

Milestone: 8.0.2
Status: closedmerge

comment:14 Changed 2 years ago by bgamari

Status: mergeclosed

comment:15 Changed 2 years ago by facundo.dominguez

Differential Rev(s): Phab:D2286Phab:D2286 Phab:D2519
Owner: facundo.dominguez deleted
Resolution: fixed
Status: closednew

comment:16 Changed 2 years ago by facundo.dominguez

Owner: set to facundo.dominguez

comment:17 Changed 2 years ago by facundo.dominguez

Status: newpatch

After last fix,

g :: Int
g = 0

f = $(do addModFinalizer $ reify (mkName "g") >>= ...
         [| return () |]
     )

couldn't find g.

comment:18 Changed 2 years ago by goldfire

When you set the status as patch, do you mean that you've fixed this shortcoming?

comment:19 Changed 2 years ago by facundo.dominguez

I hope so in a patch I submitted today https://phabricator.haskell.org/D2519.

comment:20 Changed 2 years ago by facundo.dominguez

Cc: bgamari added

comment:21 Changed 2 years ago by bgamari

Milestone: 8.0.28.2.1

Bumping off to 8.0.3.

comment:22 Changed 2 years ago by facundo.dominguez

Resolution: fixed
Status: patchclosed

Closing this as we now have #12818 to track patch D2519.

Note: See TracTickets for help on using tickets.