should TcCanonical.rewriteEvidence preserve ctev_nosh?

Nicolas Frisby nicolas.frisby at
Sat Jun 1 03:24:14 UTC 2019

A bit of context and then my question.
declares `rewriteEvidence` with the comment that "rewriteEvidence old_ev
new_pred co  ... Returns a new_ev : new_pred, with same
wanted/given/derived flag as old_ev".

However, the `CtWanted` case just immediately calls `newWanted`, which
ignores the incoming `ctev_nosh` flag and always uses `WDeriv`.

rewriteEvidence ev@(CtWanted { ctev_dest = dest

                             , ctev_loc = loc }) new_pred co

= do { mb_new_ev <- newWanted loc new_pred

(This is true in 8.6.5 and also right now at

Thus I'm seeing a [W] is become a [WD], which seems to contradict the
comment's "same flag" claim.

MY QUESTION ======> Is this "WD unsplitting" the intended behavior? See
canonicalization tc-trace below.

If it is intended, I'll probably write a follow-up question asking for more
advice. The constraint solver is looping unproductively because my plugin
keeps discarding the (re-)emitted [D] shadow as a tautology, then the [W]
"unsplits" during canonicalization (even though my plugin didn't touch the
[W]), this re-emits the same [D] (via a fundep), and so on.

My continual disclaimer recently is that I'm seeing this behavior with my
in-development plugin activated, so it's entirely I'm pushing GHC into
unfamiliar waters or even just plain violating some invariants without
realizing it. But this trace looks rather isolated from plugins.

Thanks! -Nick

Here's a -ddump-tc-trace of a canonicalization that goes from [W] to [WD]
happen (with GHC 8.6.5):

runStage canonicalization {
  workitem   =  [W] $dMonadFree_a35V {0}:: MonadFree
                                             ((fs_a2UF[sk:1] :- Const
                                              :+ Const e_a2UE[sk:1])
                                             (Free fs_a2UF[sk:1]) (CDictCan)
flatten_args {
  (fs_a2UF[sk:1] :- Const e_a2UE[sk:1]) :+ Const e_a2UE[sk:1]
  Free fs_a2UF[sk:1]
  Matching: (fs_a2UF[sk:1] :- Const e_a2UE[sk:1])
            :+ Const e_a2UE[sk:1]
  Match failed
  Matching: fs_a2UF[sk:1] :- Const e_a2UE[sk:1]
  Match failed
Unfilled tyvar fs_a2UF[sk:1]
Unfilled tyvar e_a2UE[sk:1]
flatten/flat-cache hit
  :- [* -> *, fs_a2UF[sk:1], Const e_a2UE[sk:1]]
Unfilled tyvar s_a35Z[fmv:1]
Unfilled tyvar e_a2UE[sk:1]
  Matching: s_a35Z[fmv:1] :+ Const e_a2UE[sk:1]
  Match failed
New coercion hole: co_a365
Emitting new coercion hole
  {co_a365} :: (s_a35Z[fmv:1] :+ Const e_a2UE[sk:1])
               GHC.Prim.~# s_a364[fmv:1]
  :+ [* -> *, s_a35Z[fmv:1], Const e_a2UE[sk:1]]
flatten/flat-cache miss
  :+ [* -> *, s_a35Z[fmv:1], Const e_a2UE[sk:1]]
  [WD] hole{co_a365} {0}:: (s_a35Z[fmv:1] :+ Const e_a2UE[sk:1])
                           GHC.Prim.~# s_a364[fmv:1]
Unfilled tyvar fs_a2UF[sk:1]
flatten }
  Free fs_a2UF[sk:1]
Emitting new wanted
  $dMonadFree_a366 :: MonadFree s_a364[fmv:1] (Free fs_a2UF[sk:1])
  arising from a use of ‘wrap’ at tests/ill-typed/T7.hs:77:14-17
  [W] $dMonadFree_a35V
    = $dMonadFree_a366
      `cast` ((MonadFree
                 (Sym {co_a365} ; ((:+)
                                     <* -> *>_N (Sym {co_a360}) <Const
                 <Free fs_a2UF[sk:1]>_N)_R
              :: MonadFree s_a364[fmv:1] (Free fs_a2UF[sk:1])
                 ~R# MonadFree
                       ((fs_a2UF[sk:1] :- Const e_a2UE[sk:1]) :+ Const
                       (Free fs_a2UF[sk:1]))
  [W] $dMonadFree_a35V {0}:: MonadFree
                               ((fs_a2UF[sk:1] :- Const e_a2UE[sk:1]) :+
Const e_a2UE[sk:1])
                               (Free fs_a2UF[sk:1])
  MonadFree s_a364[fmv:1] (Free fs_a2UF[sk:1])
  ContinueWith [WD] $dMonadFree_a366 {0}:: MonadFree
                                             s_a364[fmv:1] (Free
end stage canonicalization }

and later

  [WD] $dMonadFree_a36h {0}:: MonadFree
                                s_a36f[fmv:1] (Free fs_a2UF[sk:1])
emitFunDepDeriveds 1
  [fs_a2UF[sk:1] ~ s_a36f[fmv:1]]
Emitting new derived equality
  [D] _ {0}:: fs_a2UF[sk:1] GHC.Prim.~# s_a36f[fmv:1]

and then my plugin discards that [D] as a tautological, and then the [W]
gets unsplit and the [D] comes back around etc
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the ghc-devs mailing list