import FunDeps
import PrelInfo
import PrelNames
-import Type
import TysWiredIn
import ErrUtils
import BasicTypes
import FiniteMap
import Bag
import Outputable
-import Maybes
import ListSetOps
import Util
import SrcLoc
; 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
tcSimplifyRuleLhs :: [Inst] -> TcM ([Inst], TcDictBinds)
tcSimplifyRuleLhs wanteds
= do { wanteds' <- zonkInsts wanteds
- ; (irreds, binds) <- go [] emptyBag wanteds'
+
+ -- Simplify equalities
+ -- It's important to do this: Trac #3346 for example
+ ; (_, wanteds'', tybinds, binds1) <- tcReduceEqs [] wanteds'
+ ; execTcTyVarBinds tybinds
+
+ -- Simplify other constraints
+ ; (irreds, binds2) <- go [] emptyBag wanteds''
+
+ -- Report anything that is left
; let (dicts, bad_irreds) = partition isDict irreds
; traceTc (text "tcSimplifyrulelhs" <+> pprInsts bad_irreds)
; addNoInstanceErrs (nub bad_irreds)
-- The nub removes duplicates, which has
-- not happened otherwise (see notes above)
- ; return (dicts, binds) }
+
+ ; return (dicts, binds1 `unionBags` binds2) }
where
go :: [Inst] -> TcDictBinds -> [Inst] -> TcM ([Inst], TcDictBinds)
go irreds binds []
\begin{code}
tcSimplifyBracket :: [Inst] -> TcM ()
tcSimplifyBracket wanteds
- = do { tryHardCheckLoop doc wanteds
+ = do { _ <- tryHardCheckLoop doc wanteds
; return () }
where
doc = text "tcSimplifyBracket"
-- 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
where
extended_defaulting = interactive || dopt Opt_ExtendedDefaultRules dflags
+ -- See also Trac #1974
ovl_strings = dopt Opt_OverloadedStrings dflags
unaries :: [(Inst, Class, TcTyVar)] -- (C tv) constraints
-> TcM () -- Just does unification, to fix the default types
disambigGroup default_tys dicts
- = try_default default_tys
+ = do { mb_chosen_ty <- try_default default_tys
+ ; case mb_chosen_ty of
+ Nothing -> return ()
+ Just chosen_ty -> do { _ <- unifyType chosen_ty (mkTyVarTy tyvar)
+ ; warnDefault dicts chosen_ty } }
where
(_,_,tyvar) = ASSERT(not (null dicts)) head dicts -- Should be non-empty
classes = [c | (_,c,_) <- dicts]
- try_default [] = return ()
+ try_default [] = return Nothing
try_default (default_ty : default_tys)
= tryTcLIE_ (try_default default_tys) $
do { tcSimplifyDefault [mkClassPred clas [default_ty] | clas <- classes]
-- For example, if Real a is reqd, but the only type in the
-- default list is Int.
- -- After this we can't fail
- ; warnDefault dicts default_ty
- ; unifyType default_ty (mkTyVarTy tyvar)
- ; return () -- TOMDO: do something with the coercion
+ ; return (Just default_ty) -- TOMDO: do something with the coercion
}
(friends, others) = partition is_friend insts
loc_msg = showSDoc (pprInstLoc (instLoc inst))
is_friend friend = showSDoc (pprInstLoc (instLoc friend)) == loc_msg
- do_one insts = addInstCtxt (instLoc (head insts)) (report_err insts)
+ do_one insts = setInstCtxt (instLoc (head insts)) (report_err insts)
-- Add location and context information derived from the Insts
-- Add the "arising from..." part to a message about bunch of dicts
warnDefault :: [(Inst, Class, Var)] -> Type -> TcM ()
warnDefault ups default_ty = do
warn_flag <- doptM Opt_WarnTypeDefaults
- addInstCtxt (instLoc (head (dicts))) (warnTc warn_flag warn_msg)
+ setInstCtxt (instLoc (head (dicts))) (warnTc warn_flag warn_msg)
where
dicts = [d | (d,_,_) <- ups]