Specialising through specialised method calls (#19644)
In #19644 (closed), we discovered that the ClassOp/DFun rules from Note [ClassOp/DFun selection] inhibit transitive specialisation in a scenario like
class C a where m :: Show b => a -> b -> ...; n :: ...
instance C Int where m = ... -- $cm :: Show b => Int -> b -> ...
f :: forall a b. (C a, Show b) => ...
f $dC $dShow = ... m @a $dC @b $dShow ...
main = ... f @Int @Bool ...
After we specialise f
for Int
, we'll see m @a $dC @b $dShow
in the body of
$sf
. But before this patch, Specialise doesn't apply the ClassOp/DFun rule to
rewrite to a call of the instance method for C Int
, e.g., $cm @Bool $dShow
.
As a result, Specialise couldn't further specialise $cm
for Bool
.
There's a better example in Note [Specialisation modulo dictionary selectors]
.
This patch enables proper Specialisation, as follows:
- In the App case of
specExpr
, try to apply the CalssOp/DictSel rule on the head of the application - Attach an unfolding to freshly-bound dictionary ids such as
$dC
and$dShow
inbindAuxiliaryDict
NB: Without (2), (1) would be pointless, because lookupRule
wouldn't be able
to look into the RHS of $dC
to see the DFun.
(2) triggered #21332 (closed), because the Specialiser floats around dictionaries without
accounting for them in the SpecEnv
's InScopeSet
, triggering a panic when
rewriting dictionary unfoldings.
Fixes #19644 (closed) and #21332 (closed).