[GHC] #13959: substTyVar's definition is highly dubious

GHC ghc-devs at haskell.org
Thu Jul 20 08:35:29 UTC 2017


#13959: substTyVar's definition is highly dubious
-------------------------------------+-------------------------------------
        Reporter:  RyanGlScott       |                Owner:  (none)
            Type:  bug               |               Status:  patch
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              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):  Phab:D3732
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by simonpj):

 > Who arranges for the members of the in-scope set to have substituted
 kinds?

 Well, if the in-scope set comes from the context (as in the simplifier or
 other places) all the `Var`s in the in-scope set are `OutIds`; that is,
 fully substituted.  It would be wrong to substitute again, because it's
 entirely OK to have a substitution that goes `a :-> [a]`, because the LHS
 is `InVars` and the RHS is `OutVaers`.  (This is not true during
 unification of course, but that's entirely separate.)

 E.g.  a substitution   [a :-> Proxy k (b::k),  k :-> *]  really means
 "replace `a` by `Proxy k (b::k)`" and NOT "then apply the subsituton to
 the result to get `Proxy * (b::*)`.  No no no.  Substitutions apply
 exactly once.

 (In this example the `k` in `Proxy k (b::k)` is an `OutTyVar` whereas the
 `k` in `k :-> *` is an `InTyVar`.)


 What if we build the in-scope set by taking the free vars of the range of
 the substitution?  Eg.
 {{{
 Substitute  [a :-> Proxy k (b::k)]
 in the type (a, b)
 }}}
 The in-scope set, from the range of the substitution, is {b,k}.   Do we
 need to apply the substitution to {b}?  No!  The range of the substitution
 is `OutVars` so we must not apply the substitution to it.

 A more delicate point is this: what if we build (part of) the in-scope set
 by taking the free vars of the type being substituted (see
 `substTyAddInScope` and `Note [The substitution invariant]` in`TyCoRep`?
 That's an `InType`!  eg
 {{{
 Substitute  [a :-> Int]
 in the type (a, b::k)
 }}}
 Now we get an in-scope set of `{b::k}`.  But although `b` appears in an
 `InType`, it must be an `OutTyVar` precisely because it is not
 substituted.  It must be bound somewhere outside, and it'd be wrong to
 substitute its kind at one of its occurrences and not at its binding site!

 So I think everything is fine.  But I really wish I had a clearer way to
 explain WHY it is fine.

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


More information about the ghc-tickets mailing list