#5375: Regression in newName
---------------------------------+------------------------------------------
    Reporter:  reinerp           |        Owner:                           
        Type:  bug               |       Status:  new                      
    Priority:  normal            |    Milestone:                           
   Component:  Template Haskell  |      Version:  7.3                      
    Keywords:                    |     Testcase:                           
   Blockedby:                    |   Difficulty:                           
          Os:  Unknown/Multiple  |     Blocking:                           
Architecture:  Unknown/Multiple  |      Failure:  GHC rejects valid program
---------------------------------+------------------------------------------

Comment(by simonpj):

 Aha. This is a consequence of fixing another bug #5037!  (See also `Note
 [Binders in Template Haskell]` in source:compiler/hsSyn/Convert.lhs.)
 Consider this:
 {{{
 x = 4
 y = $(do { x <- newName "x"; return (LamE (VarP x) (VarE (mkName "x"))) })
 }}}
 So the ''binder'' is made with `newName`, but the ''occurrence'' is made
 with `mkName` (the "dynamic binding" bit of TH).  Clearly, I think, the
 occurrence should should bind to the lambda, not to the top-level x.  So
 the defns should end up thus:
 {{{
 -- Like this
    x = 4
    y = \x -> x

 -- NOT like this
    x = 4
    y = \x' -> x
 }}}
 Similarly, what do you think should happen here:
 {{{
 $( do { x <- newName "x"; return (ValD (VarP x) (LitE 3)) } )
 v = x
 }}}
 Current the `newName` expands to something that captures the `x` below the
 splice:
 {{{
 -- We get this
   x = 3
   v = x

 -- NOT this
   x' = 3
   v = x
 }}}
 Remember too that the `newName` stuff is what happens behind the scences
 with a quotation like `[d| x = 3 |]`.

 For your data type example, suppose we had
 {{{
 -- declare 'data E = D' with a fresh name 'D'
 $(do
     nm <- newName "D"
     return $ [DataD [] (mkName "E") [] [NormalC nm []] []] )

 f :: E
 f = D
 }}}
 Wouldn't you expect the `D` in the defn of F to bind to the `D` declared
 by the spliced data type decl?  Just as if you'd written
 {{{
 data E = D
 f :: E
 f = D
 }}}
 Remember, again, that quotation uses `newName` for binders, and you'd
 ''definitely'' expect this to expand to the above code:
 {{{
 $( [d| data E = D |] )
 f :: E
 f = D
 }}}
 In short, it seems to me that the "multiple definitions" thing is right.
 But I accept that:
  * There is therefore no way to splice in a data type decl that is
 guaranteed not to clash with any existing one.  That's bad.  (In the case
 of terms, lambdas etc simply ''shadow'' existing defns, so the problem
 doesn't arise.)  Maybe we need a way to make a fresh name that can be
 referred to ''only'' by knowing the name, and not by `mkName` or by open
 Haskell code?

  * The "internal error" message from the type checker is terrible.

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/5375#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler

_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs

Reply via email to