Generating fresh names in a source plugin
[Since it seems that `glasgow-haskell-users@haskell.org` is essentially an announcements-only mailing list these days, I’m re-sending my recent e-mail to that mailing list here.] Hello! I want to generate AST fragments in a source plugin, and for this I need to generate fresh (local) names. My current approach is to use `mkSystemName`, but it, like many of the other name-generating operations, needs a value of type `Unique`. How can I generate such values? It seems that the `Hsc` monad doesn’t carry a value of type `UniqueSupply` with it. All the best, Wolfgang
Hello, again! After some more digging, I came to the conclusion that `uniqFromTag` is likely what I should use. However, what exactly is the tag for? The note „Uniques and tags“ only says the following:
The tag […] is typically used to make it easier to distinguish uniques constructed by different parts of the compiler.
Who distinguishes uniques using tags: the compiler, compiler developers when reading debugging output, or end users? Does the choice of tag influence the behavior of the compiler other than with respect to messages? The documentation of `mkSplitUniqSupply` says that the tag “is mostly cosmetic”. If it is only *mostly* cosmetic, what aspects of it are not cosmetic? In the end, how do I choose a tag for uniques generated by a plugin? Is the choice essentially irrelevant? Do I have to prevent clashes with tags used by GHC or other plugins? Looking forward to insights. 🙂 All the best, Wolfgang Am Samstag, dem 02.08.2025 um 16:16 +0300 schrieb Wolfgang Jeltsch:
Hello!
I want to generate AST fragments in a source plugin, and for this I need to generate fresh (local) names. My current approach is to use `mkSystemName`, but it, like many of the other name-generating operations, needs a value of type `Unique`. How can I generate such values? It seems that the `Hsc` monad doesn’t carry a value of type `UniqueSupply` with it.
All the best, Wolfgang
Hi,
what I have used In the past (and that I am fairly confident works) is exactly what you say: use `uniqFromTag` or `mkSplitUniqSupply`.
According to the documentation, "the payload part of the Uniques allocated from this UniqSupply are guaranteed distinct wrt all other supplies, regardless of their 'tag'."
(Assuming the unique does not overflow it's number of bits)
As far as I know, end users should not get to see a unique and it should not influence compilation, so the Tag is only relevant for plugin/GHC devs for debugging.
Also just curious: why do you need to construct a unique? Before the GHC renamer a plugin can get away with generating essentially strings that are "unique" and use them in `mkUnqual` or similar.
Most of the time, I just generate a `RdrName` with a prefix that would not be allowed in source code with an incrementing suffix that I manage myself.
I have not checked if a plugin-generated name has to be a valid Haskell name nowadays. However, it worked in the past.
And just for completeness if someone else stumbles across this: After the GHC renamer in `CoreM`, `TcM` (and others) one can just use `getUniqueM` or `getUniqueSupplyM`.
Best wishes,
Kai Prott
On August 2, 2025 7:08:10 PM GMT+02:00, Wolfgang Jeltsch
Hello, again!
After some more digging, I came to the conclusion that `uniqFromTag` is likely what I should use. However, what exactly is the tag for?
The note „Uniques and tags“ only says the following:
The tag […] is typically used to make it easier to distinguish uniques constructed by different parts of the compiler.
Who distinguishes uniques using tags: the compiler, compiler developers when reading debugging output, or end users? Does the choice of tag influence the behavior of the compiler other than with respect to messages?
The documentation of `mkSplitUniqSupply` says that the tag “is mostly cosmetic”. If it is only *mostly* cosmetic, what aspects of it are not cosmetic?
In the end, how do I choose a tag for uniques generated by a plugin? Is the choice essentially irrelevant? Do I have to prevent clashes with tags used by GHC or other plugins?
Looking forward to insights. 🙂
All the best, Wolfgang
Am Samstag, dem 02.08.2025 um 16:16 +0300 schrieb Wolfgang Jeltsch:
Hello!
I want to generate AST fragments in a source plugin, and for this I need to generate fresh (local) names. My current approach is to use `mkSystemName`, but it, like many of the other name-generating operations, needs a value of type `Unique`. How can I generate such values? It seems that the `Hsc` monad doesn’t carry a value of type `UniqueSupply` with it.
All the best, Wolfgang
ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Hi,
what I have used In the past (and that I am fairly confident works) is exactly what you say: use `uniqFromTag` or `mkSplitUniqSupply`.
According to the documentation, "the payload part of the Uniques allocated from this UniqSupply are guaranteed distinct wrt all other supplies, regardless of their 'tag'." (Assuming the unique does not overflow it's number of bits) If you read on the docs refer to an edge case in the next lines. GHC contains a (limited) number of fixed/"built in" uniques. GHC itself never creates uniques with the same tag as those fixed ones on the fly so there is no risk of collision. However if you explicitly use this tag it could happen and then compilation could go wrong. Outside of this
Some slight additions to Kais message: On 03/08/2025 17:25, Kai Prott wrote: that is correct.
As far as I know, end users should not get to see a unique and it should not influence compilation, so the Tag is only relevant for plugin/GHC devs for debugging.
Uniques influence code generation slightly, as they are part of internal symbol names. They should however not affect the behaviour of the program. This doesn't matter often, but when it does it really does.
Also just curious: why do you need to construct a unique? Before the GHC renamer a plugin can get away with generating essentially strings that are "unique" and use them in `mkUnqual` or similar. Most of the time, I just generate a `RdrName` with a prefix that would not be allowed in source code with an incrementing suffix that I manage myself. I have not checked if a plugin-generated name has to be a valid Haskell name nowadays. However, it worked in the past.
And just for completeness if someone else stumbles across this: After the GHC renamer in `CoreM`, `TcM` (and others) one can just use `getUniqueM` or `getUniqueSupplyM`.
Best wishes, Kai Prott
On August 2, 2025 7:08:10 PM GMT+02:00, Wolfgang Jeltsch
wrote: Hello, again! After some more digging, I came to the conclusion that `uniqFromTag` is likely what I should use. However, what exactly is the tag for? The note „Uniques and tags“ only says the following:
The tag […] is typically used to make it easier to distinguish uniques constructed by different parts of the compiler.
Who distinguishes uniques using tags: the compiler, compiler developers when reading debugging output, or end users? Does the choice of tag influence the behavior of the compiler other than with respect to messages? The documentation of `mkSplitUniqSupply` says that the tag “is mostly cosmetic”. If it is only *mostly* cosmetic, what aspects of it are not cosmetic? In the end, how do I choose a tag for uniques generated by a plugin? Is the choice essentially irrelevant? Do I have to prevent clashes with tags used by GHC or other plugins? Looking forward to insights. 🙂 All the best, Wolfgang Am Samstag, dem 02.08.2025 um 16:16 +0300 schrieb Wolfgang Jeltsch:
Hello! I want to generate AST fragments in a source plugin, and for this I need to generate fresh (local) names. My current approach is to use `mkSystemName`, but it, like many of the other name-generating operations, needs a value of type `Unique`. How can I generate such values? It seems that the `Hsc` monad doesn’t carry a value of type `UniqueSupply` with it. All the best, Wolfgang
------------------------------------------------------------------------ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Am Montag, dem 04.08.2025 um 16:12 +0200 schrieb Andreas Klebinger:
On 03/08/2025 17:25, Kai Prott wrote:
According to the documentation, "the payload part of the Uniques allocated from this UniqSupply are guaranteed distinct wrt all other supplies, regardless of their 'tag'." (Assuming the unique does not overflow it's number of bits)
If you read on the docs refer to an edge case in the next lines. GHC contains a (limited) number of fixed/"built in" uniques. GHC itself never creates uniques with the same tag as those fixed ones on the fly so there is no risk of collision. However if you explicitly use this tag it could happen and then compilation could go wrong. Outside of this that is correct.
I think there is at least another tag that is treated specially: `f`, having to do with type families, from what I remember. The fact that some tags do cause special compiler behavior makes the situation quite tricky. It may seem that a plugin author should pick a tag that isn’t used by GHC. This is already difficult, because you can’t reliably tell what tags GHC uses and what tags it may use in the future. However, what if the tags of the uniques that the plugin generates *need* special treatment? For example, you may want to create uniques for local variables that your plugin introduces, and GHC may use a tag for uniques of local names that causes necessary special compiler behavior. In the end, I used `grep` and my own eyes to check potentially the whole GHC codebase for tag use. My conclusion is that likely no specially treated tag is used for local variables, which are what I want the uniques for. Therefore, I probably should pick a tag that GHC surely doesn’t use and won’t ever use. I guess I’ll go for some ASCII control character. All the best, Wolfgang
think there is at least another tag that is treated specially: `f`, having to do with type families, from what I remember. The fact that some tags do cause special compiler behavior makes the situation quite tricky.
If you believe that the tag has significance beyond debugging etc, you may be right -- *but can you point to any evidence? *Perhaps you can record what you learn on #26264? It may seem that a plugin author should pick a
tag that isn’t used by GHC. This is already difficult, because you can’t reliably tell what tags GHC uses and what tags it may use in the future. However, what if the tags of the uniques that the plugin generates *need* special treatment? For example, you may want to create uniques for local variables that your plugin introduces, and GHC may use a tag for uniques of local names that causes necessary special compiler behavior.
Once again, I know of no "special compiler behaviour" but I may be wrong.
you can’t reliably tell what tags GHC uses and what tags it may use in the future. In the end, I used `grep` and my own eyes to check potentially the whole GHC codebase for tag use.
Indeed this is bad. Can you record the list of tags you discovered, and
where they are born, in #26264?
Thanks!
Simon
On Mon, 4 Aug 2025 at 23:06, Wolfgang Jeltsch
Am Montag, dem 04.08.2025 um 16:12 +0200 schrieb Andreas Klebinger:
On 03/08/2025 17:25, Kai Prott wrote:
According to the documentation, "the payload part of the Uniques allocated from this UniqSupply are guaranteed distinct wrt all other supplies, regardless of their 'tag'." (Assuming the unique does not overflow it's number of bits)
If you read on the docs refer to an edge case in the next lines. GHC contains a (limited) number of fixed/"built in" uniques. GHC itself never creates uniques with the same tag as those fixed ones on the fly so there is no risk of collision. However if you explicitly use this tag it could happen and then compilation could go wrong. Outside of this that is correct.
I think there is at least another tag that is treated specially: `f`, having to do with type families, from what I remember.
The fact that some tags do cause special compiler behavior makes the situation quite tricky. It may seem that a plugin author should pick a tag that isn’t used by GHC. This is already difficult, because you can’t reliably tell what tags GHC uses and what tags it may use in the future. However, what if the tags of the uniques that the plugin generates *need* special treatment? For example, you may want to create uniques for local variables that your plugin introduces, and GHC may use a tag for uniques of local names that causes necessary special compiler behavior.
In the end, I used `grep` and my own eyes to check potentially the whole GHC codebase for tag use. My conclusion is that likely no specially treated tag is used for local variables, which are what I want the uniques for. Therefore, I probably should pick a tag that GHC surely doesn’t use and won’t ever use. I guess I’ll go for some ASCII control character.
All the best, Wolfgang _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
There's supposed to be one already, IIRC. And indeed, there is `Note [Uniques for wired-in prelude things and known tags]` in compiler/GHC/Builtin/Uniques.hs. If you've found more, they should probably be added there. On Mon, Aug 4, 2025 at 6:19 PM Simon Peyton Jones < simon.peytonjones@gmail.com> wrote:
think there is at least another tag that is treated specially: `f`,
having to do with type families, from what I remember. The fact that some tags do cause special compiler behavior makes the situation quite tricky.
If you believe that the tag has significance beyond debugging etc, you may be right -- *but can you point to any evidence? *Perhaps you can record what you learn on #26264?
It may seem that a plugin author should pick a
tag that isn’t used by GHC. This is already difficult, because you can’t reliably tell what tags GHC uses and what tags it may use in the future. However, what if the tags of the uniques that the plugin generates *need* special treatment? For example, you may want to create uniques for local variables that your plugin introduces, and GHC may use a tag for uniques of local names that causes necessary special compiler behavior.
Once again, I know of no "special compiler behaviour" but I may be wrong.
you can’t reliably tell what tags GHC uses and what tags it may use in the future. In the end, I used `grep` and my own eyes to check potentially the whole GHC codebase for tag use.
Indeed this is bad. Can you record the list of tags you discovered, and where they are born, in #26264?
Thanks!
Simon
On Mon, 4 Aug 2025 at 23:06, Wolfgang Jeltsch
wrote: Am Montag, dem 04.08.2025 um 16:12 +0200 schrieb Andreas Klebinger:
On 03/08/2025 17:25, Kai Prott wrote:
According to the documentation, "the payload part of the Uniques allocated from this UniqSupply are guaranteed distinct wrt all other supplies, regardless of their 'tag'." (Assuming the unique does not overflow it's number of bits)
If you read on the docs refer to an edge case in the next lines. GHC contains a (limited) number of fixed/"built in" uniques. GHC itself never creates uniques with the same tag as those fixed ones on the fly so there is no risk of collision. However if you explicitly use this tag it could happen and then compilation could go wrong. Outside of this that is correct.
I think there is at least another tag that is treated specially: `f`, having to do with type families, from what I remember.
The fact that some tags do cause special compiler behavior makes the situation quite tricky. It may seem that a plugin author should pick a tag that isn’t used by GHC. This is already difficult, because you can’t reliably tell what tags GHC uses and what tags it may use in the future. However, what if the tags of the uniques that the plugin generates *need* special treatment? For example, you may want to create uniques for local variables that your plugin introduces, and GHC may use a tag for uniques of local names that causes necessary special compiler behavior.
In the end, I used `grep` and my own eyes to check potentially the whole GHC codebase for tag use. My conclusion is that likely no specially treated tag is used for local variables, which are what I want the uniques for. Therefore, I probably should pick a tag that GHC surely doesn’t use and won’t ever use. I guess I’ll go for some ASCII control character.
All the best, Wolfgang _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
-- brandon s allbery kf8nh allbery.b@gmail.com
Am Montag, dem 04.08.2025 um 18:37 -0400 schrieb Brandon Allbery:
And indeed, there is `Note [Uniques for wired-in prelude things and known tags]` in compiler/GHC/Builtin/Uniques.hs.
This doesn’t list which tags cause special compiler behavior, only which ones are used by GHC in general. Also, it is by no means clear that this list is comprehensive. It seems that its authors were partly even unsure about tag meaning: the entry for tag `a` has a question mark. Finally, this list leaves questions open. It sometimes only mentions compiler components to which certain tags are related but not for what kinds of uniques they are actually used (and not even whether said uniques are introduced or used by the mentioned compiler components). All the best, Wolfgang
Right, so I'm suggesting that any changes or additions should be recorded
in that Note so it can be the primary source of information on tags that it
apparently wanted to be. And perhaps it deserves special mention in
the Commentary as such.
On Tue, Aug 5, 2025 at 10:26 AM Wolfgang Jeltsch
Am Montag, dem 04.08.2025 um 18:37 -0400 schrieb Brandon Allbery:
And indeed, there is `Note [Uniques for wired-in prelude things and known tags]` in compiler/GHC/Builtin/Uniques.hs.
This doesn’t list which tags cause special compiler behavior, only which ones are used by GHC in general.
Also, it is by no means clear that this list is comprehensive. It seems that its authors were partly even unsure about tag meaning: the entry for tag `a` has a question mark.
Finally, this list leaves questions open. It sometimes only mentions compiler components to which certain tags are related but not for what kinds of uniques they are actually used (and not even whether said uniques are introduced or used by the mentioned compiler components).
All the best, Wolfgang _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
-- brandon s allbery kf8nh allbery.b@gmail.com
Am Montag, dem 04.08.2025 um 23:18 +0100 schrieb Simon Peyton Jones:
you can’t reliably tell what tags GHC uses and what tags it may use in the future. In the end, I used `grep` and my own eyes to check potentially the whole GHC codebase for tag use.
Indeed this is bad. Can you record the list of tags you discovered, and where they are born, in #26264?
If I’d only remember what they were. I think I remember at least how I performed this check. I may perform it again once I’ll find the time. All the best, Wolfgang
Am Dienstag, dem 05.08.2025 um 17:18 +0300 schrieb Wolfgang Jeltsch:
Am Montag, dem 04.08.2025 um 23:18 +0100 schrieb Simon Peyton Jones:
you can’t reliably tell what tags GHC uses and what tags it may use in the future. In the end, I used `grep` and my own eyes to check potentially the whole GHC codebase for tag use.
Indeed this is bad. Can you record the list of tags you discovered, and where they are born, in #26264?
If I’d only remember what they were. I think I remember at least how I performed this check. I may perform it again once I’ll find the time.
I pretended that I had time immediately and searched again. The results are at https://gitlab.haskell.org/ghc/ghc/-/issues/26264#note_630286 and in the follow-up comments of mine. All the best, Wolfgang
Am Sonntag, dem 03.08.2025 um 17:25 +0200 schrieb Kai Prott:
Also just curious: why do you need to construct a unique? Before the GHC renamer a plugin can get away with generating essentially strings that are "unique" and use them in `mkUnqual` or similar.
Most of the time, I just generate a `RdrName` with a prefix that would not be allowed in source code with an incrementing suffix that I manage myself. I have not checked if a plugin-generated name has to be a valid Haskell name nowadays. However, it worked in the past.
I briefly considered this approach but then rejected it, because I couldn’t be sure that syntactically incorrect names are accepted and because there would be a slim possibility that another plugin picks names that my plugin picks. All the best, Wolfgang
What about calling this function?
GHC.Tc.Plugin.newUnique :: TcPluginM Unique
The module GHC.Tc.Plugin provides facilities to plugins.
More generally, here is the manual page for plugins
https://ghc.gitlab.haskell.org/ghc/doc/users_guide/extending_ghc.html#compil....
Is it adequate?
I notice that
- it mentions the module GHC.Plugins (but only in code fragments)
- it does not mention GHC.Tc.Plugins; neither does GHC.Plugins re-export
GHC.Tc.Plugins
It would be great if some plugin authors felt able to offer patches to
improve. Maybe open a GHC ticket?
Simon
On Sat, 2 Aug 2025 at 14:16, Wolfgang Jeltsch
[Since it seems that `glasgow-haskell-users@haskell.org` is essentially an announcements-only mailing list these days, I’m re-sending my recent e-mail to that mailing list here.]
Hello!
I want to generate AST fragments in a source plugin, and for this I need to generate fresh (local) names. My current approach is to use `mkSystemName`, but it, like many of the other name-generating operations, needs a value of type `Unique`. How can I generate such values? It seems that the `Hsc` monad doesn’t carry a value of type `UniqueSupply` with it.
All the best, Wolfgang _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Ugh. I realise that you were talking about *source* plugins, which work in
the Hsc monad, which indeed has no obvious way to generate uniques.
I have created https://gitlab.haskell.org/ghc/ghc/-/issues/26264 to
document my learning journey.
Simon
On Mon, 4 Aug 2025 at 11:44, Simon Peyton Jones
What about calling this function?
GHC.Tc.Plugin.newUnique :: TcPluginM Unique
The module GHC.Tc.Plugin provides facilities to plugins.
More generally, here is the manual page for plugins https://ghc.gitlab.haskell.org/ghc/doc/users_guide/extending_ghc.html#compil.... Is it adequate?
I notice that
- it mentions the module GHC.Plugins (but only in code fragments) - it does not mention GHC.Tc.Plugins; neither does GHC.Plugins re-export GHC.Tc.Plugins
It would be great if some plugin authors felt able to offer patches to improve. Maybe open a GHC ticket?
Simon
On Sat, 2 Aug 2025 at 14:16, Wolfgang Jeltsch
wrote: [Since it seems that `glasgow-haskell-users@haskell.org` is essentially an announcements-only mailing list these days, I’m re-sending my recent e-mail to that mailing list here.]
Hello!
I want to generate AST fragments in a source plugin, and for this I need to generate fresh (local) names. My current approach is to use `mkSystemName`, but it, like many of the other name-generating operations, needs a value of type `Unique`. How can I generate such values? It seems that the `Hsc` monad doesn’t carry a value of type `UniqueSupply` with it.
All the best, Wolfgang _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Am Montag, dem 04.08.2025 um 15:16 +0100 schrieb Simon Peyton Jones:
I have created https://gitlab.haskell.org/ghc/ghc/-/issues/26264 to document my learning journey.
Thank you for this. I find the reference to `takeUniqFromNameCache` interesting. I understand that the name cache that a `Hsc` environment contains, stores a tag that is to be used for generating uniques of names that will be put into this cache. I guess that for generating my own names I may use this very tag. All the best, Wolfgang
participants (5)
-
Andreas Klebinger -
Brandon Allbery -
Kai Prott -
Simon Peyton Jones -
Wolfgang Jeltsch