-- irreds2 will be empty. But we don't want to generalise over b!
; let preds2 = fdPredsOfInsts irreds2 -- irreds2 is zonked
qtvs = growInstsTyVars irreds2 tau_tvs2 `minusVarSet` oclose preds2 gbl_tvs2
+ ---------------------------------------------------
+ -- BUG WARNING: there's a nasty bug lurking here
+ -- fdPredsOfInsts may return preds that mention variables quantified in
+ -- one of the implication constraints in irreds2; and that is clearly wrong:
+ -- we might quantify over too many variables through accidental capture
+ ---------------------------------------------------
; let (free, irreds3) = partition (isFreeWhenInferring qtvs) irreds2
; extendLIEs free
; env' <- zonkRedEnv env
; wanteds' <- zonkInsts wanteds
- ; (improved, binds, irreds) <- reduceContext env' wanteds'
+ ; (improved, tybinds, binds, irreds)
+ <- reduceContext env' wanteds'
+ ; execTcTyVarBinds tybinds
; if null irreds || not improved then
return (irreds, binds)
-- HOWEVER, some unification may take place, if we instantiate
-- a method Inst with an equality constraint
; let env = mkNoImproveRedEnv doc (\_ -> ReduceMe)
- ; (_imp, _binds, constrained_dicts) <- reduceContext env wanteds_z
+ ; (_imp, _tybinds, _binds, constrained_dicts)
+ <- reduceContext env wanteds_z
-- Next, figure out the tyvars we will quantify over
; tau_tvs' <- zonkTcTyVarsAndFV (varSetElems tau_tvs)
ppr _binds,
ppr constrained_tvs', ppr tau_tvs', ppr qtvs ])
- -- Zonk wanteds again! The first call to reduceContext may have
- -- instantiated some variables.
- -- FIXME: If red_improve would work, we could propagate that into
- -- the equality solver, too, to prevent instantating any
- -- variables.
- ; wanteds_zz <- zonkInsts wanteds_z
-
-- The first step may have squashed more methods than
-- necessary, so try again, this time more gently, knowing the exact
-- set of type variables to quantify over.
(is_nested_group || isDict inst) = Stop
| otherwise = ReduceMe
env = mkNoImproveRedEnv doc try_me
- ; (_imp, binds, irreds) <- reduceContext env wanteds_zz
+ ; (_imp, tybinds, binds, irreds) <- reduceContext env wanteds_z
+ ; execTcTyVarBinds tybinds
-- See "Notes on implicit parameters, Question 4: top level"
; ASSERT( all (isFreeWrtTyVars qtvs) irreds ) -- None should be captured
-- Unusually for checking, we *must* zonk the given_ips
; let env = mkRedEnv doc try_me given_ips'
- ; (improved, binds, irreds) <- reduceContext env wanteds'
+ ; (improved, tybinds, binds, irreds) <- reduceContext env wanteds'
+ ; execTcTyVarBinds tybinds
; if null irreds || not improved then
ASSERT( all is_free irreds )
reduceContext :: RedEnv
-> [Inst] -- Wanted
-> TcM (ImprovementDone,
+ TcTyVarBinds, -- Type variable bindings
TcDictBinds, -- Dictionary bindings
[Inst]) -- Irreducible
givens = red_givens env
; (givens',
wanteds',
- normalise_binds,
- eq_improved) <- tcReduceEqs givens wanteds
+ tybinds,
+ normalise_binds) <- tcReduceEqs givens wanteds
; traceTc $ text "reduceContext: tcReduceEqs result" <+> vcat
- [ppr givens', ppr wanteds', ppr normalise_binds]
+ [ppr givens', ppr wanteds', ppr tybinds,
+ ppr normalise_binds]
-- Build the Avail mapping from "given_dicts"
; (init_state, _) <- getLIE $ do
-- Collect all irreducible instances, and determine whether we should
-- go round again. We do so in either of two cases:
-- (1) If dictionary reduction or equality solving led to
- -- improvement (i.e., instantiated type variables).
+ -- improvement (i.e., bindings for type variables).
-- (2) If we reduced dictionaries (i.e., got dictionary bindings),
-- they may have exposed further opportunities to normalise
-- family applications. See Note [Dictionary Improvement]
; let all_irreds = dict_irreds ++ implic_irreds ++ extra_eqs
avails_improved = availsImproved avails
+ eq_improved = anyBag (not . isCoVarBind) tybinds
improvedFlexible = avails_improved || eq_improved
reduced_dicts = not (isEmptyBag dict_binds)
improved = improvedFlexible || reduced_dicts
text "given" <+> ppr givens,
text "wanted" <+> ppr wanteds0,
text "----",
+ text "tybinds" <+> ppr tybinds,
text "avails" <+> pprAvails avails,
text "improved =" <+> ppr improved <+> text improvedHint,
text "(all) irreds = " <+> ppr all_irreds,
]))
; return (improved,
+ tybinds,
normalise_binds `unionBags` dict_binds
`unionBags` implic_binds,
all_irreds)
}
+ where
+ isCoVarBind (TcTyVarBind tv _) = isCoVar tv
tcImproveOne :: Avails -> Inst -> TcM ImprovementDone
tcImproveOne avails inst