Skip to content

TcPlugins: newWanted discards the source location

When a plugin spins off a new Wanted constraint, using newWanted, based on a constraint it can simplify, the source location for the constraint is discarded.

This happens because we have:

-- GHC.Tc.Plugin
newWanted :: CtLoc -> PredType -> TcPluginM CtEvidence
newWanted loc pty
  = unsafeTcPluginTcM (TcM.newWanted (ctLocOrigin loc) Nothing pty)

-- GHC.Tc.Utils.TcMType
newWanted :: CtOrigin -> Maybe TypeOrKind -> PredType -> TcM CtEvidence
newWanted orig t_or_k pty
  = do loc <- getCtLocM orig t_or_k
       d <- if isEqPrimPred pty then HoleDest  <$> newCoercionHole pty
                                else EvVarDest <$> newEvVar pty
       return $ CtWanted { ctev_dest = d
                         , ctev_pred = pty
                         , ctev_nosh = WDeriv
                         , ctev_loc = loc }

-- GHC.Tc.Utils.Monad
getCtLocM :: CtOrigin -> Maybe TypeOrKind -> TcM CtLoc
getCtLocM origin t_or_k
  = do { env <- getLclEnv
       ; return (CtLoc { ctl_origin = origin
                       , ctl_env    = env
                       , ctl_t_or_k = t_or_k
                       , ctl_depth  = initialSubGoalDepth }) }

That is, starting with the CtLoc (which has the source span information we want), we keep only the CtOrigin, and discard the rest. The typechecker environment is then obtained from the monadic environment with getLclEnv in getCtLocM.

In practice, in a typechecking plugin, when one wants the emitted Wanted to have the same source location, one must wrap the newWanted call in setCtLocM. This sets the correct typechecker environment that to be retrieved by getLcLEnv.

If GHC.Tc.Plugin.newWanted is going to discard the local typechecking environment, then it should clearly indicate so in its type signature by taking a CtOrigin instead of a CtLoc.

@rae @nfrisby Do either of you have opinions on how to design the API to avoid this problem? Also tagging @edsko as he has been running into this issue.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information