[GHC] #12249: Template Haskell top level scoping error

#12249: Template Haskell top level scoping error -------------------------------------+------------------------------------- Reporter: simonpj | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Template | Version: 8.0.1 Haskell | Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: None/Unknown Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- Consider this {{{ module TH where $( [d| x = True; f1 = x |]) $( [d| x = 'c'; f2 = x |] ) }}} I think this should compile fine. There are two bindings of `x`, so I would not expect to be able to name `x` in the export list, or indeed anywhere else. But `x` may just be a local helper-function to the other bindings (`f1` and `f2` resp) so that's fine. Alas I get {{{ ~/5builds/HEAD-4/inplace/bin/ghc-stage2 -c TH.hs -ddump-splices -ddump-tc TH.hs:5:4-26: Splicing declarations [d| x_apA = True f1_apB = x_apA |] ======> x_a3tN = True f1_a3tO = x_a3tN TH.hs:7:4-25: Splicing declarations [d| x_a3u4 = 'c' f2_a3u5 = x_a3u4 |] ======> x_a3uW = 'c' f2_a3uX = x_a3uW TH.hs:7:4: error: Multiple declarations of ‘x’ Declared at: TH.hs:5:4 TH.hs:7:4 TH.hs:7:4: error: The exact Name ‘x_a3uW’ is not in scope Probable cause: you used a unique Template Haskell name (NameU), perhaps via newName, but did not bind it If that's it, then -ddump-splices might be useful }}} So: * Perhaps we should not complain about multiple top-level bindings for `x` if they are all `Exact` RdrNames. * And the "not in scope" message is clearly bogus. Mind you, would you expect this to work? {{{ x = True $( [d| x = 'c'; f2 = x |] ) foo = x -- Which 'x' do we get? }}} Maybe the occurrence of `x` in `foo` is ambiguous. If you want to splice a hidden helper binding, which can't clash with some earlier or later user-supplied thing, then use an occurrence like `$x`. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12249 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12249: Template Haskell top level scoping error -------------------------------------+------------------------------------- Reporter: simonpj | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Template Haskell | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by goldfire): Perhaps the error message is regrettable, but otherwise, I like the original behavior. You say in your original example that `x` is not available for export or other use outside of the splices. But then why should `f1` or `f2` be? Is it only that they are unambiguous? What about {{{ $([d| x = 5 |]) y = x $([d| x = 7 |]) }}} That's unambiguous. But surely confusing! Could you write a specification of your intended behavior? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12249#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12249: Template Haskell top level scoping error -------------------------------------+------------------------------------- Reporter: simonpj | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Template Haskell | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): Yes, it's only that they are unambiguous.
Could you write a specification of your intended behavior?
Yes. Occurrences are OK if they are unambiguous. That's it really. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12249#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12249: Template Haskell top level scoping error -------------------------------------+------------------------------------- Reporter: simonpj | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Template Haskell | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by goldfire): OK. But why do we want this behavior? Would it simplify the implementation? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12249#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12249: Template Haskell top level scoping error -------------------------------------+------------------------------------- Reporter: simonpj | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Template Haskell | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj):
But why do we want this behavior?
Consider the code in the Description. It seems perfectly reasonable to me; the two quasiquotes both bind 'x' but in each case it's clear what binds the occurrence of `x` on the RHS of `f1`, `f2`. I'm thinking of splices that generate a wad of code that needs some auxiliary bindings; we don't want to have to worry about a clash if we happen to re-use the same name when generating the auxiliary bindings in a different splice. For example, `deriving` code. In fact it's this that is causing #12245, although that code is generated by GHC itself, not by TH, but it's the same idea. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12249#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12249: Template Haskell top level scoping error -------------------------------------+------------------------------------- Reporter: simonpj | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Template Haskell | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by goldfire): Hm. I suppose I've run into the same issue when writing `singletons`. But isn't this what `newName` is for? Currently, `newName` doesn't always do a good enough job at creating a top-level name that's fresh even between splices, but I'm sure we could fix it. In effect, you're trying to turn TH into a module/namespace system, where some apparently-top-level declarations actually have a limited scope. Whether or not a definition is local or global depends on the entire file, instead of being listed in one spot. While what you propose may be readily implementable, I would say that it may be time better spent designing a proper module/namespace system that TH could use. As you've designed this feature, I could see people (perhaps even including myself) using TH only for your new module-like capabilities. For example, when writing papers, I often use the same variable names in different examples. When I extract my code and compile the papers, these overlapping variable names cause annoyance. If you implement your feature, then I would put some TH dingbats in my extraction engine to avoid the ambiguous variable uses/redefinitions... but this is abusive of TH. Clearly, compiling academic papers is not the primary use-case for Haskell (or is it? I suppose it once was!) but I'm sure I'm not the only one who would do such shenanigans. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12249#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12249: Template Haskell top level scoping error -------------------------------------+------------------------------------- Reporter: simonpj | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Template Haskell | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj):
But isn't this what newName is for?
Well, no. `newName` is a last resort when quasiquotation won't work. Quasiquotes are the preferred way of creating lexically scoped binders. And even `newName` will create a new name with distinct unique but the same occurrence name, which will give the same "Two top level bindings for `x`" error. I don't think I'm trying to build a new module/namespace system. In Haskell 2010, it's ok to import two different functions both called `f` provided you don't refer to `f` unqualified. It's the same here. If I mention `x` I expect a complaint about ambiguity; but if I don't I expect it to be fine. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12249#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12249: Template Haskell top level scoping error -------------------------------------+------------------------------------- Reporter: simonpj | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Template Haskell | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by goldfire): Your last comment suggests a way to think about all of this: Each ''declaration group'' (as defined in the [https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts... #template-haskell manual]) is its own unnamed module that exports all of its symbols. That actually might not be a bad way of implementing it either. (And `newName` identifiers should never be exported, as per discussion in comment:13:ticket:10599, yet to be finished.) In any case, I still say you're building some sort of ad-hoc implicit module system. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12249#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC