#2806: Require bang-patterns for unlifted bindings
---------------------------------+------------------------------------------
    Reporter:  simonpj           |        Owner:                  
        Type:  feature request   |       Status:  new             
    Priority:  normal            |    Milestone:  6.12.1          
   Component:  Compiler          |      Version:  6.8.3           
    Severity:  normal            |   Resolution:                  
    Keywords:                    |   Difficulty:  Unknown         
    Testcase:                    |           Os:  Unknown/Multiple
Architecture:  Unknown/Multiple  |  
---------------------------------+------------------------------------------
Comment (by simonpj):

 Just to record an email exchange.

 Ian Lynagh:
 {{{
 It looks like TcBinds.checkStrictBinds is the place to do it.

 If we have where clauses
     where (b, I# a) = ...
     where (b, I# !a) = ...
 then we respectively get
     mbind = <(b, GHC.Types.I# a) = ...>
     mbind = <(b, GHC.Types.I# !a) = ...>
     mono_tys = [(), GHC.Prim.Int#]
     mono_tys = [(), GHC.Prim.Int#]
 but where I get stuck is trying to match up the types with the bangs (or
 lack of bangs). One option would be to walk over mbind, but that feels
 rather hackish - especially as it's a bag rather than a list! Another
 might be to put a boolean for the presence or absence of a bang in the
 MonoBindInfo, and then to pair it with the type when making mono_tys.
 }}}
 Simon PJ replies:
 {{{
 | It looks like TcBinds.checkStrictBinds is the place to do it.

 I agree.

 | If we have where clauses
 |     where (b, I# a) = ...
 |     where (b, I# !a) = ...

 Whoa!  I think this is *not* what's proposed.  Suppose we have

         let (x, !y) = e in ...

 This is *not* evaluated strictly.  Rather, if 'x' is evaluated,
 the pattern is matched, and hence y is evaluated at that moment.
 Similarly if 'y' is evaluated, but that makes no difference.
 Having a bang on the 'y' doesn't force strict evaluation of the pattern.

 In contrast, if we have

         let (x, I# y) = e in ..

 then we *must* evaluate the whole let strictly (because y:Int#)
 so we demand a bang on the whole pattern not on the 'y'.
 So we should have written

         let !(x, I# y) = in in ...
 }}}
 Ian says:
 {{{
 Oh, wow, you are right. So lifted and unlifted bindings wouldn't behave
 uniformly after all:

 foo1 = 'a'
     where !(x, ~(y, !z))   = ('x', ('y', 1 `div` 0))

 foo2 = 'a'
     where !(x, ~(y, I# z)) = ('x', ('y', 1 `div` 0))

 foo1 == 'a', but foo2 == _|_

 Even more distressing is:

 foo3 = 'a'
     where !(x, ~(!y, !z))   = ('x', (1 `div` 0, (3 :: Int)))

 foo4 = 'a'
     where !(x, ~(!y, I# z)) = ('x', (1 `div` 0, (3 :: Int)))

 Again foo3 == 'a' and foo4 == _|_, but in this case it is the evaluation
 of !y that is the source of the _|_.

 So perhaps ~p, where p contains an unlifted variable, should be rejected
 too?
 }}}
 Simon says
 {{{
 Yes, absolutely it should.  Let's do that at the same time.
 I'm not 100% sure where the best place is.  Presumably in TcPat, since
         \~(x, I# y) -> ...
 should also be rejected.

 But when checking a ~pattern, we don't have conveniently to hand
 the variables bound.

 I suspect the easiest thing is going to be in
         tc_pat (LazyPat ...)
 to do (getPatBinders pat') and check for un-lifted types.
 }}}

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/2806#comment:4>
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