Skip to content

Banish reportFloatingViaTvs to the shadow realm (#15831, #16181)

Ryan Scott requested to merge RyanGlScott/ghc:wip/T15831 into master

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 (closed) 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 (closed), so this patch fixes that issue too.

Fixes #15831 (closed). Fixes #16181 (closed).

Edited by Ryan Scott

Merge request reports