Skip to content
  • Ryan Scott's avatar
    Banish reportFloatingViaTvs to the shadow realm (#15831, #16181) · 30b6f391
    Ryan Scott authored and Marge Bot's avatar Marge Bot committed
    GHC used to reject programs of this form:
    
    ```
    newtype Age = MkAge Int
      deriving Eq via Const Int a
    ```
    
    That's because an earlier implementation of `DerivingVia` would
    generate the following instance:
    
    ```
    instance Eq Age where
      (==) = coerce @(Const Int a -> Const Int a -> Bool)
                    @(Age         -> Age         -> Bool)
                    (==)
    ```
    
    Note that the `a` in `Const Int a` is not bound anywhere, which
    causes all sorts of issues. I figured that no one would ever want to
    write code like this anyway, so I simply banned "floating" `via` type
    variables like `a`, checking for their presence in the aptly named
    `reportFloatingViaTvs` function.
    
    `reportFloatingViaTvs` ended up being implemented in a subtly
    incorrect way, as #15831 demonstrates. Following counsel with the
    sage of gold fire, I decided to abandon `reportFloatingViaTvs`
    entirely and opt for a different approach that would _accept_
    the instance above. This is because GHC now generates this instance
    instead:
    
    ```
    instance forall a. Eq Age where
      (==) = coerce @(Const Int a -> Const Int a -> Bool)
                    @(Age         -> Age         -> Bool)
                    (==)
    ```
    
    Notice that we now explicitly quantify the `a` in
    `instance forall a. Eq Age`, so everything is peachy scoping-wise.
    See `Note [Floating `via` type variables]` in `TcDeriv` for the full
    scoop.
    
    A pleasant benefit of this refactoring is that it made it much easier
    to catch the problem observed in #16181, so this patch fixes that
    issue too.
    
    Fixes #15831. Fixes #16181.
    30b6f391