- go [] ty = return ([], Check ty)
- go (pat:pats) ty = unifyFunTy ty `thenM` \ (arg,res) ->
- go pats res `thenM` \ (pats_w_tys, final_res) ->
- return ((pat, Check arg) : pats_w_tys, final_res)
-
-unifyFunTy :: TcRhoType -- Fail if ty isn't a function type
- -> TcM (TcType, TcType) -- otherwise return arg and result types
-
-unifyFunTy ty@(TyVarTy tyvar)
- = getTcTyVar tyvar `thenM` \ maybe_ty ->
- case maybe_ty of
- Just ty' -> unifyFunTy ty'
- Nothing -> unify_fun_ty_help ty
-
-unifyFunTy ty
- = case tcSplitFunTy_maybe ty of
- Just arg_and_res -> returnM arg_and_res
- Nothing -> unify_fun_ty_help ty
-
-unify_fun_ty_help ty -- Special cases failed, so revert to ordinary unification
- = newTyVarTy argTypeKind `thenM` \ arg ->
- newTyVarTy openTypeKind `thenM` \ res ->
- unifyTauTy ty (mkFunTy arg res) `thenM_`
- returnM (arg,res)
+ mk_msg n_actual
+ = error_herald <> comma $$
+ sep [ptext SLIT("but its type") <+> quotes (pprType ty),
+ if n_actual == 0 then ptext SLIT("has none")
+ else ptext SLIT("has only") <+> speakN n_actual]
+
+unify_fun_ty :: Bool -> Arity -> TcRhoType
+ -> TcM (Bool, -- Arity satisfied?
+ [TcSigmaType], -- Arg types found; length <= arity
+ TcRhoType) -- Result type
+
+unify_fun_ty use_refinement arity ty
+ | arity == 0
+ = do { res_ty <- wobblify use_refinement ty
+ ; return (True, [], ty) }
+
+unify_fun_ty use_refinement arity ty
+ | Just ty' <- tcView ty
+ = unify_fun_ty use_refinement arity ty'
+
+unify_fun_ty use_refinement arity ty@(TyVarTy tv)
+ = do { details <- condLookupTcTyVar use_refinement tv
+ ; case details of
+ IndirectTv use' ty' -> unify_fun_ty use' arity ty'
+ DoneTv (MetaTv ref) -> ASSERT( liftedTypeKind `isSubKind` tyVarKind tv )
+ -- The argument to unifyFunTys is always a type
+ -- Occurs check can't happen, of course
+ do { args <- mappM newTyFlexiVarTy (replicate arity argTypeKind)
+ ; res <- newTyFlexiVarTy openTypeKind
+ ; writeMutVar ref (Indirect (mkFunTys args res))
+ ; return (True, args, res) }
+ DoneTv skol -> return (False, [], ty)
+ }
+
+unify_fun_ty use_refinement arity ty
+ | Just (arg,res) <- tcSplitFunTy_maybe ty
+ = do { arg' <- wobblify use_refinement arg
+ ; (ok, args', res') <- unify_fun_ty use_refinement (arity-1) res
+ ; return (ok, arg':args', res') }
+
+unify_fun_ty use_refinement arity ty
+-- Common cases are all done by now
+-- At this point we usually have an error, but ty could
+-- be (a Int Bool), or (a Bool), which can match
+-- So just use the unifier. But catch any error so we just
+-- return the success/fail boolean
+ = do { arg <- newTyFlexiVarTy argTypeKind
+ ; res <- newTyFlexiVarTy openTypeKind
+ ; let fun_ty = mkFunTy arg res
+ ; (_, mb_unit) <- tryTc (uTys True ty ty True fun_ty fun_ty)
+ ; case mb_unit of {
+ Nothing -> return (False, [], ty) ;
+ Just _ ->
+ do { (ok, args', res') <- unify_fun_ty use_refinement (arity-1) res
+ ; return (ok, arg:args', res')
+ } } }