[GHC] #14231: Core lint error "in result of Static argument"

GHC ghc-devs at haskell.org
Wed Jul 4 11:30:05 UTC 2018


#14231: Core lint error "in result of Static argument"
-------------------------------------+-------------------------------------
        Reporter:  mpickering        |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  8.5
      Resolution:                    |             Keywords:
                                     |  StaticArgumentTransformation
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 osa1):

 This module has a few problems:

 - The nofib results in the module documentation are not valid anymore. I
 just
   run nofib with GHC 8.4.2 and this pass made 0 difference in allocations.

 - The running example used in documentation doesn't really work anymore.
 For
   some reason this pass doesn't transform the `map` function.

 - The pass reuses ids in binder position (i.e. binds same ids with same
 uniques
   etc. multiple times), without cloning them (probably to avoid renaming).
 I
   think this may break invariants in other places in the compiler although
 I'm
   not sure.

 Now, for this specific ticket, here's the function before SAT:

 {{{
 bindWith :: forall a. (a -> a) -> a -> a
 bindWith
   = \ (@ a_a17W) (k_atr :: a_a17W -> a_a17W) (f_ats :: a_a17W) ->
       k_atr (bindWith @ a_a17W k_atr f_ats)
 }}}

 After SAT:

 {{{
 bindWith :: forall a. (a -> a) -> a -> a
 bindWith
   = \ (@ a_a17W) (k_atr :: a_a17W -> a_a17W) (f_ats :: a_a17W) ->
       letrec {
         sat_worker_s198 :: a_a17W
         [LclId]
         sat_worker_s198
           = let {
               bindWith_r1 :: forall a. (a_a17W -> a_a17W) -> a_a17W ->
 a_a17W
               [LclId]
               bindWith_r1
                 = \ (@ a_s195) (k_s196 :: a_a17W -> a_a17W) (f_s197 ::
 a_a17W) ->
                     sat_worker_s198 } in
             k_atr (bindWith @ a_a17W k_atr f_ats); } in
       sat_worker_s198,
 }}}

 (The printer doesn't make it clear but `bindWith_r1` and `bindWith` have
 the
 same unique)

 The problem is if you ignore uniques all those `a` type variables are the
 same,
 but from the type checker's perspective they're not, which can be seen in
 the
 linter error. With `-dsuppress-uniques`:

 {{{
 Mismatch in type between binder and occurrence
 Var: bindWith
 Binder type: forall a. (a -> a) -> a -> a
 Occurrence type: forall a. (a -> a) -> a -> a
   Before subst: forall a. (a -> a) -> a -> a
 }}}

 With uniques:

 {{{
 Mismatch in type between binder and occurrence
 Var: bindWith_r1
 Binder type: forall a. (a_a17W -> a_a17W) -> a_a17W -> a_a17W
 Occurrence type: forall a. (a -> a) -> a -> a
   Before subst: forall a. (a -> a) -> a -> a
 }}}

 SAT never actually builds types, it builds terms and then calls
 `exprType`. The
 incorrect type `forall a. (a_a17W -> a_a17W) -> a_a17W -> a_a17W` is given
 to
 this term by `exprType`:

 {{{
 \ (@ a_s195) (k_s196 :: a_a17W -> a_a17W) (f_s197 :: a_a17W) ->
     sat_worker_s198
 }}}

 Arguments of this lambda is generated by this (probably broken) clone
 function:

 {{{
 clone (bndr, NotStatic) = return bndr
 clone (bndr, _        ) = do { uniq <- newUnique
                              ; return (setVarUnique bndr uniq) }
 }}}

 Where the second element of the pair is defined like this:

 {{{
 data App = VarApp Id | TypeApp Type | CoApp Coercion
 data Staticness = Static App | NotStatic
 }}}

 So this clones types, coercion, and term binders just by generating a new
 unique for them. I'm not sure if this is right way to clone binders. Then,
 as I
 said above, it reuses some ids in binder position without cloning them. I
 suspect one or both of them are causing this bug.

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


More information about the ghc-tickets mailing list